Skip to content

JavaScript: preserve sanitizer barriers on guarded phi inputs - #23005

Open
nikhilred2619 wants to merge 3 commits into
github:mainfrom
nikhilred2619:fix/js-sanitizer-guard-phi-inputs-22848
Open

nikhilred2619 wants to merge 3 commits into
github:mainfrom
nikhilred2619:fix/js-sanitizer-guard-phi-inputs-22848

Conversation

@nikhilred2619

Copy link
Copy Markdown

Fixes #22848.

This change fixes false positives caused by sanitizer guards being lost across SSA phi inputs.

The fix preserves branch-specific barriers while keeping direct flow edges for inputs without a dominating condition.

I also added regression tests covering safe fallbacks, guarded loops, incorrect guard conditions, reflected XSS, and resource exhaustion. The existing spurious alert in UnsafeShellCommandConstruction is removed.

Testing: All 21 affected tests passed locally.

Related PR: #22873 addresses the same underlying issue. This version additionally limits synthetic phi-input nodes to guarded predecessor blocks and includes broader regression coverage.

Happy to make any adjustments based on feedback.

nd = DataFlow::valueNode(use)
)
or
exists(BarrierGuard guard, DataFlowPrivate::SsaPhiInputNode input |
override Location getLocation() { result = expr.getLocation() }
}

/** One incoming edge of an SSA phi, represented as a node so guards can block it. */
Copilot AI auto review requested due to automatic review settings November 11, 2026 10:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Captured-variable phi inputs are assigned to the wrong callable, breaking local flow and discarding call context, while the regression test lacks a recognized remote-input source.

3 open issues
What changed in this PR

Addresses #22848 by preserving branch-specific sanitizer guards when JavaScript and TypeScript values merge after fallback assignments, reducing false-positive security alerts.

Changes:

  • Introduces guarded phi-input nodes while retaining direct flow for unguarded inputs.
  • Adds fixtures for safe fallbacks, loops, incorrect guards, reflected XSS, and resource exhaustion.
  • Refreshes expected results, removes an existing spurious shell-command alert, and adds a change note.
File Description
javascript/​ql/​test/​query-tests/​Security/​CWE-770/​ResourceExhaustion/​resource-exhaustion.js Adds a clamped-allocation scenario.
javascript/​ql/​test/​query-tests/​Security/​CWE-079/​ReflectedXss/​ReflectedXssGood.js Adds allowlist and regular-expression fallback scenarios.
javascript/​ql/​test/​query-tests/​Security/​CWE-078/​UnsafeShellCommandConstruction/​UnsafeShellCommandConstruction.expected Removes the spurious alert and related path output.
javascript/​ql/​test/​query-tests/​Security/​CWE-078/​UnsafeShellCommandConstruction/​lib/​lib.js Changes the expectation comment to mark the sanitized command as safe.
javascript/​ql/​test/​library-tests/​TaintTracking/​sanitizer-guards.js Adds guarded-merge regression fixtures.
javascript/​ql/​test/​library-tests/​TaintTracking/​DataFlowTracking.expected Refreshes data-flow results and removes a resolved legacy mismatch.
javascript/​ql/​test/​library-tests/​TaintTracking/​BasicTaintTracking.expected Refreshes taint-flow results for the guard fixtures.
javascript/​ql/​lib/​semmle/​javascript/​dataflow/​internal/​DataFlowPrivate.qll Defines synthetic phi-input data-flow nodes.
javascript/​ql/​lib/​semmle/​javascript/​dataflow/​internal/​DataFlowNode.qll Creates phi-input nodes for guarded predecessors.
javascript/​ql/​lib/​semmle/​javascript/​dataflow/​internal/​BarrierGuards.qll Applies sanitizer barriers to individual phi inputs.
javascript/​ql/​lib/​semmle/​javascript/​dataflow/​DataFlow.qll Splits guarded phi edges while retaining direct unguarded flow.
javascript/​ql/​lib/​semmle/​javascript/​dataflow/​Configuration.qll Adapts legacy edge barriers to phi-input nodes.
javascript/​ql/​lib/​change-notes/​2026-11-03-sanitizer-guard-phi-inputs.md Documents the sanitizer-guard improvement.

Review effort: Max (auto)

override string toString() { result = "[ssa-phi-input] " + phi.toString() }

cached
override StmtContainer getContainer() { result = phi.getSourceVariable().getDeclaringContainer() }
Comment on lines +107 to +113
function clampedAllocation(req) {
let n = parseInt(req.query.n);
if (n > 1024) {
n = 1024;
}
Buffer.alloc(n); // OK - n is at most 1024 (or an invalid allocation size)
}
Comment on lines +1746 to +1748
exists(SsaPhiNode phi, BasicBlock bb |
pred = TSsaDefNode(phi.getInputFromBlock(bb).getDefinition()) and
succ = TSsaPhiInputNode(phi, bb)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JS: Some sanitizer guards no longer apply after if (!check(x)) x = default (false positives since 2.20.2)

3 participants