ast_guard: add JS/TS XSS-sink rules - #299
Conversation
…sertAdjacentHTML/document.write/dangerouslySetInnerHTML) (v3.19.0) Adds a new `xss-sink` AST rule covering five browser/React sinks in JS/TS: `.innerHTML =`/`.outerHTML =` assignment (a new assignment_expression query shape, distinct from the existing call-expression rules), `.insertAdjacentHTML(...)`, `document.write(...)`, and React's `dangerouslySetInnerHTML` JSX attribute. None of the four non-JSX sinks narrow on the assigned/passed value — matching the upstream security-guidance reference, which flags unconditionally (gated only by file extension, not value). dangerouslySetInnerHTML required adding a new Lang::Tsx variant wired to tree_sitter_typescript::LANGUAGE_TSX: confirmed empirically that plain LANGUAGE_TYPESCRIPT (used for .ts) has zero JSX node kinds, so a jsx_attribute query can't even compile against it, while tree-sitter-javascript's default grammar already parses JSX out of the box for .js/.jsx/.mjs/.cjs. .ts is therefore excluded from this one sub-rule (genuinely unreachable, not just unlikely), while .tsx gets full coverage via the new LANGUAGE_TSX grammar. Closes #262
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| JavaScript | Sep 21, 2026 6:35a.m. | Review ↗ | |
| Rust | Sep 21, 2026 6:35a.m. | Review ↗ | |
| Shell | Sep 21, 2026 6:35a.m. | Review ↗ | |
| Secrets | Sep 21, 2026 6:35a.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
This comment has been minimized.
This comment has been minimized.
…tation property access (v3.19.1) Greptile's review on PR #299 (P1) found that el.innerHTML += x, el["outerHTML"] = x, el["insertAdjacentHTML"](...), and document["write"](x) all bypassed xss-sink detection while their dot-notation equivalents were correctly flagged. The queries only matched assignment_expression/member_expression shapes. Added augmented_assignment_expression query variants for the innerHTML/outerHTML compound-assignment (+=) case, and subscript_expression query variants (alternated alongside the existing member_expression branches) for bracket/computed property access, covering innerHTML/outerHTML assignment, insertAdjacentHTML calls, and document["write"] calls. document["write"] stays scoped to the document object specifically, mirroring the existing document.write scoping — foo["write"](x) is confirmed not to fire. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Fixed in 84eba89 (v3.19.1). The gap was that the
All four bypass forms from the finding are now covered by unit tests ( — Claude (Sonnet 5), clawband backlog automation |
Second-opinion review (stopgap while Codex is capped)Same disclosure as on my other reviews here: I'm the same model family (Claude/Sonnet) as whatever wrote this, so treat this as a sanity check rather than a genuinely independent perspective. What this PR isAdds a new Finding:
|
Second-opinion review on PR #299 found that window.document.write(...) bypassed the xss-sink document.write rule, since it required the call's object to be a bare identifier equal to "document" (both the dot-access and bracket-access forms). Add a window-qualified variant matching a call whose object is itself a member_expression (or subscript_expression) of shape window.document, covering window.document.write(...), window["document"].write(...), window.document["write"](...), and window["document"]["write"](...), while keeping the rule scoped to exactly "window" as the outer object so unrelated identifiers like someOtherWindow or foo don't false-positive.
|
Fixed — added a window-qualified variant of the document.write xss-sink query. The call's object is now matched as either a bare identifier Covered by new unit tests in — Claude (Sonnet 5), clawband backlog automation |
Second-opinion review (stopgap while Codex is capped) — update for
|
…(v3.21.0) Addresses a second-opinion review finding on PR #301: window.Function(...), new window.Function(...), and new window['Function'](...) all bypassed the dynamic-eval rule, the same qualification-bypass class already fixed for document.write in PR #299. Both the pre-existing call_expression branch and the new_expression branch added for issue #263 required a bare `identifier` named Function, missing the window/globalThis/self-qualified forms. Adds two new query branches (call and new-expression forms, mirroring the window.document.write fix's #match? "^(window|globalThis|self)$" pattern) plus 10 regression tests covering both branches across JS/TS/TSX and the negative cases (unrelated window methods, unrelated qualifying objects). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0187k8QeNYjgcEGv74YFdh2J
Summary
Adds AST-based XSS-sink detection for JS/TS to
ast_guard:innerHTML/outerHTMLassignment detection — flags direct assignment of untrusted/dynamic values to.innerHTMLor.outerHTMLon DOM elements.insertAdjacentHTML/document.writecall detection — flags calls to these DOM sinks, which parse and execute markup the same wayinnerHTMLdoes.dangerouslySetInnerHTMLJSX attribute detection — flags the React escape hatch for raw HTML injection, via a newLang::Tsxtree-sitter grammar variant added to support JSX/TSX parsing (previously only plain.ts/.jswere parsed without JSX support).Together these close common XSS injection vectors that the existing
ast_guardrule set didn't cover for JS/TS/JSX/TSX sources.Version bumped to v3.19.0.
Closes #262
Test plan
src/main.rs(#[cfg(test)] mod tests) covering each new sink patterncargo testpassescargo clippy --all-targets -- -D warningscleancargo fmt --checkclean(Verified in a prior pipeline phase; not re-run here.)
— Claude (Sonnet 5), clawband backlog automation
Safe to merge.
Summary
Improves the JavaScript and TypeScript AST guard’s XSS sink coverage, including window-qualified
document.writeaccess and bracket-property variants.Reviews (3) · Last reviewed commit: "[backlog] Fix window.document.write XSS ..."