diff --git a/src/job.c b/src/job.c
index 7533553f..d145bef9 100644
--- a/src/job.c
+++ b/src/job.c
@@ -2886,7 +2886,7 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
     return 0;
 
   if (shellflags == 0)
-    shellflags = posix_pedantic ? "-ec" : "-c";
+    shellflags = posix_pedantic && NONE_SET (flags, COMMANDS_NOERROR) ? "-ec" : "-c";
 
   /* See if it is safe to parse commands internally.  */
   if (shell == 0)
@@ -3710,6 +3710,7 @@ construct_command_argv (char *line, char **restp, struct file *file,
   char **argv;
 
   {
+    struct variable *var;
     /* Turn off --warn-undefined-variables while we expand SHELL and IFS.  */
     int save = warn_undefined_variables_flag;
     warn_undefined_variables_flag = 0;
@@ -3770,7 +3771,15 @@ construct_command_argv (char *line, char **restp, struct file *file,
     }
 #endif /* __EMX__ */
 
-    shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file);
+    var = lookup_variable_for_file (STRING_SIZE_TUPLE (".SHELLFLAGS"), file);
+    if (!var)
+      shellflags = xstrdup ("");
+    else if (posix_pedantic && var->origin == o_default)
+      /* In POSIX mode we default to -ec, unless we're ignoring errors.  */
+      shellflags = xstrdup (ANY_SET (cmd_flags, COMMANDS_NOERROR) ? "-c" : "-ec");
+    else
+      shellflags = allocated_variable_expand_for_file (var->value, file);
+
     ifs = allocated_variable_expand_for_file ("$(IFS)", file);
 
     warn_undefined_variables_flag = save;
diff --git a/src/variable.c b/src/variable.c
index 259093f8..ec87ce9b 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -538,6 +538,29 @@ lookup_variable (const char *name, size_t length)
 
   return 0;
 }
+/* Lookup a variable whose name is a string starting at NAME
+   and with LENGTH chars.  NAME need not be null-terminated.
+   Returns address of the 'struct variable' containing all info
+   on the variable, or nil if no such variable is defined.  */
+
+struct variable *
+lookup_variable_for_file (const char *name, size_t length, struct file *file)
+{
+  struct variable *var;
+  struct variable_set_list *savev;
+
+  if (file == NULL)
+    return lookup_variable (name, length);
+
+  savev = current_variable_set_list;
+  current_variable_set_list = file->variables;
+
+  var = lookup_variable (name, length);
+
+  current_variable_set_list = savev;
+
+  return var;
+}
 
 /* Lookup a variable whose name is a string starting at NAME
    and with LENGTH chars in set SET.  NAME need not be null-terminated.
diff --git a/src/variable.h b/src/variable.h
index c7bbe8f5..244da4f8 100644
--- a/src/variable.h
+++ b/src/variable.h
@@ -182,6 +182,8 @@ void define_new_function(const floc *flocp, const char *name,
                          unsigned int min, unsigned int max, unsigned int flags,
                          gmk_func_ptr func);
 struct variable *lookup_variable (const char *name, size_t length);
+struct variable *lookup_variable_for_file (const char *name, size_t length,
+                                           struct file *file);
 struct variable *lookup_variable_in_set (const char *name, size_t length,
                                          const struct variable_set *set);
 
diff --git a/tests/scripts/targets/POSIX b/tests/scripts/targets/POSIX
index ade0b1ee..325d58cb 100644
--- a/tests/scripts/targets/POSIX
+++ b/tests/scripts/targets/POSIX
@@ -7,12 +7,52 @@ $details = "";
 
 # Ensure turning on .POSIX enables the -e flag for the shell
 
-run_make_test(qq!
+run_make_test(q!
 .POSIX:
-all: ; \@#HELPER# -q fail 1; true
+all: ; @#HELPER# -q fail 1; #HELPER# out hello
 !,
               '', "#MAKE#: *** [#MAKEFILE#:3: all] Error 1\n", 512);
 
+# But explicit settings must still take precedence
+
+run_make_test(q!
+.POSIX:
+all: ; @-#HELPER# -q fail 1; #HELPER# out hello
+.SHELLFLAGS = -c
+!,
+              '', "hello");
+
+run_make_test(q!
+.POSIX:
+all: ; @-#HELPER# -q fail 1; #HELPER# out hello
+all: .SHELLFLAGS = -c
+!,
+              '', "hello");
+
+# SV 63667: We shouldn't add -e to sh if errors are ignored
+
+run_make_test(q!
+.POSIX:
+all: ; @-#HELPER# -q fail 1; #HELPER# out hello
+!,
+              '', "hello\n");
+
+# But explicit settings must still take precedence
+
+run_make_test(q!
+.POSIX:
+all: ; @-#HELPER# -q fail 1; #HELPER# out hello
+.SHELLFLAGS = -ec
+!,
+              '', "#MAKE#: [#MAKEFILE#:3: all] Error 1 (ignored)\n");
+
+run_make_test(q!
+.POSIX:
+all: ; @-#HELPER# -q fail 1; #HELPER# out hello
+all: .SHELLFLAGS = -ec
+!,
+              '', "#MAKE#: [#MAKEFILE#:3: all] Error 1 (ignored)\n");
+
 # User settings must override .POSIX
 # In the standard .POSIX must be the first thing in the makefile
 # but we relax that rule in GNU Make.