diff --git a/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql b/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql index afa675c7f7b2..99f3e15f7e05 100644 --- a/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql +++ b/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql @@ -15,20 +15,18 @@ import java import semmle.code.java.security.CommandLineQuery import semmle.code.java.security.ExternalProcess +import semmle.code.java.security.ControlledString +import semmle.code.java.dataflow.internal.ModelExclusions /** - * Strings that are known to be sane by some simple local analysis. Such strings - * do not need to be escaped, because the programmer can predict what the string - * has in it. + * Strings that are known to be sane (controlled or compile-time constant). + * Such strings do not need to be escaped, because the programmer can predict + * what the string has in it. */ predicate saneString(Expr expr) { - expr instanceof StringLiteral + controlledString(expr) or - expr instanceof NullLiteral - or - exists(Variable var | var.getAnAccess() = expr and exists(var.getAnAssignedValue()) | - forall(Expr other | var.getAnAssignedValue() = other | saneString(other)) - ) + expr instanceof CompileTimeConstantExpr } predicate builtFromUncontrolledConcat(Expr expr) { @@ -48,5 +46,6 @@ predicate builtFromUncontrolledConcat(Expr expr) { from StringArgumentToExec argument where builtFromUncontrolledConcat(argument) and - not execIsTainted(_, _, argument) + not execIsTainted(_, _, argument) and + not isInTestFile(argument.getFile()) select argument, "Command line is built with string concatenation." diff --git a/java/ql/src/change-notes/2026-06-15-exec-unescaped-consolidated.md b/java/ql/src/change-notes/2026-06-15-exec-unescaped-consolidated.md new file mode 100644 index 000000000000..4589b2e8e03d --- /dev/null +++ b/java/ql/src/change-notes/2026-06-15-exec-unescaped-consolidated.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `java/concatenated-command-line` query now uses `controlledString` and `CompileTimeConstantExpr` instead of the previous `saneString` heuristic, reducing false positives for expressions that are known to be safe. Additionally, results in test files are now excluded.