Repository navigation
JS: Require string base in SanitizedChar - #23129
Open
sam-robson wants to merge 1 commit into
Open
sam-robson wants to merge 1 commit into
sam-robson wants to merge 1 commit into
Conversation
sam-robson
force-pushed
the
sam-robson/js-sanitizedchar-array
branch
from
November 13, 2026 14:55
9db3006 to
84fa714
Compare
sam-robson
marked this pull request as ready for review
November 13, 2026 14:56
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
A duplicate sanitizeShellString declaration overrides the original fixture helper, and the production sanitizer-classification change lacks DCA results to assess unexpected alert changes.
2 open issues
What changed in this PR
Tightens JavaScript shell-command sanitizer recognition so array elements are not mistaken for sanitized single characters.
Changes:
- Requires
SanitizedCharto have an inferred string base. - Adds string-type regression cases and updates expected alerts and data-flow paths.
- Documents the detection change and possible false positives around string conversions.
| File | Description |
|---|---|
| javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected | Updates expected alerts and data-flow paths. |
| javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js | Adds string-type regression cases and adjusts alert annotations. |
| javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll | Requires a string base for SanitizedChar. |
| javascript/ql/lib/change-notes/2026-11-13-sanitized-char-string-base.md | Documents detection changes and string-conversion limitations. |
Review effort: Max (dynamic)
| ) and | ||
| astNode.getPropertyNameExpr().analyze().getTheType() = TTNumber() | ||
| astNode.getPropertyNameExpr().analyze().getTheType() = TTNumber() and | ||
| astNode.getBase().analyze().getTheType() = TTString() |
sam-robson
force-pushed
the
sam-robson/js-sanitizedchar-array
branch
from
November 13, 2026 15:16
84fa714 to
3b3e6b6
Compare
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The test does not isolate the intended type-inference limitation, and the production query change lacks DCA evidence assessing downstream alert changes or regressions.
2 open issues
1 resolved since last review
Review effort: Max (dynamic)
| } | ||
|
|
||
| module.exports.sanitizedCharStringChecks = function (name) { // $ Source | ||
| cp.exec("rm -rf " + yetAnohterSanitizer(String(name))); // $ SPURIOUS: Alert - String(...) is not modeled by type inference |
sam-robson
force-pushed
the
sam-robson/js-sanitizedchar-array
branch
from
November 13, 2026 17:42
3b3e6b6 to
ef9e463
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Fixes #23123
SanitizedChartreatss[i]as sanitized when equality guards exclude each character ingetAShellChar()andiis a number. It does not check the type ofs, so an array element bypasses the single-character checks:Require
sto have inferred typestring:SanitizedChar() { exists(AccessPath ap | this.asExpr() = ap.getAnInstance() | forall(string char | char = getAShellChar() | blocksCharInAccess(ap, char, astNode)) ) and - astNode.getPropertyNameExpr().analyze().getTheType() = TTNumber() + astNode.getPropertyNameExpr().analyze().getTheType() = TTNumber() and + astNode.getBase().analyze().getTheType() = TTString() }