Skip to content

feat(rules): TypeScript/JavaScript XSS, path traversal and open redirect rules; more SSRF sinks (pack v1.11) - #116

Closed
chubirka wants to merge 1 commit into
developmentfrom
feat/ts-rules-xss-path-redirect
Closed

chubirka wants to merge 1 commit into
developmentfrom
feat/ts-rules-xss-path-redirect

Conversation

@chubirka

@chubirka chubirka commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

What

Vercel comparison gap plan, step 5 (A3): TypeScript/JavaScript rules, rule pack v1.11. The same rule files go to main and development in two PRs (owner decision); only the version and changelog differ.

Why these rules. The rule-mining report (confirmed true positives in the ledger) lists TS/JS's largest uncovered clusters as XSS (CWE-79, 37 findings in about 30 repos), path traversal (CWE-22, 10) and open redirect (CWE-601, 4). Prototype pollution, in the plan's original list, has no confirmed findings. Authorization asymmetry is now covered by the Express route × guard matrix (traust-core#250). Each rule is written from the cited findings' evidence.

Rule Shape
traust-ts-xss-dangerously-set-inner-html computed __html with no sanitizer; translation strings and sanitized-named values excluded
traust-ts-xss-dom-html-sink innerHTML / outerHTML / insertAdjacentHTML / document.write (also on an opened window) / jQuery .html() with a computed value
traust-ts-xss-markdown-raw-html (WARNING) rehype-raw without a later rehype-sanitize
traust-ts-xss-reflected-response-taint request value in an Express send / write / end string body
traust-ts-path-traversal-fs-taint request value (incl. destructured body, req.url/req.path) to the path argument of fs read/write/stream/remove, res.sendFile, res.download; path.basename clears
traust-ts-open-redirect-response-taint request value as res.redirect / Location target
traust-ts-open-redirect-client-navigation (WARNING) URLSearchParams.get / location.search / location.hash as the URL of location.* or window.open
traust-ts-ssrf-request-taint (extended) + http(s).request, remaining axios methods, got, superagent, needle, undici

Sinks are focused on the URL/path argument, so a tainted file body or window name doesn't match. Test, spec, mock and mock-backend files are excluded.

Measured on eight real checkouts

Run on eight real checkouts: 35 hits, including every confirmed TS/JS finding present in them.

  • By hand: about 8 real or the same shape; about 12 noise (generated documentation bundles, static docs-site content, developer-controlled placeholders, a style injection, a test helper); about 15 need a reviewer.
  • Noise removed while measuring: translation strings in dangerouslySetInnerHTML, mock servers, import.meta.url and options.path read as request paths, a window name read as a URL, and non-Express .download() calls.
  • Not covered (stay with review): javascript: URLs bound to href, markdown-to-jsx and marked renderer overrides, sanitize-then-transform pipelines.

Verification

  • opengrep test on typescript/: 16/16 passed; each new fixture's hit count equals its ruleid: lines.
  • make test green.

🤖 Generated with Claude Code

…ect rules; more SSRF sinks (pack v1.11)

Written from the confirmed TS/JS findings the rule-mining report lists as uncovered (XSS 37, path traversal 10, open redirect 4). On eight real checkouts the rules hit 35 times, including all three confirmed findings present there (console LogsPage.tsx, SharedResourceWarning.js, backend/src/routes/serve.ts). 0.40.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chubirka
chubirka requested a review from a team as a code owner October 27, 2026 22:32
@openshift-ci

openshift-ci Bot commented Oct 27, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: chubirka

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 27, 2026
@smith-xyz

Copy link
Copy Markdown
Contributor

This needs to move to traust before it can land on development.

Since traust#291, development loads the opengrep rule pack from traust at packs/security/detection/opengrep-rules/. That's now the default stack every run uses, and traust's docs-consistency gate enforces it as the only copy. The engine's src/traust_engine/data/secure-code-audit/opengrep-rules/ is a leftover the sweep stages still fall back to until they move to core (progress-tracker 11-consumer-adoption/11-shaun-core-api-only.md, piece C), when it gets deleted. Rules added here won't run in default scans on development.

Could you open this as a traust PR instead? It's a mechanical move:

  • the 8 typescript/ files into packs/security/detection/opengrep-rules/typescript/. I diffed the two copies on development and the existing rules are byte-identical, so ssrf.yaml applies cleanly;
  • the README additions into packs/security/detection/opengrep-rules/README.md;
  • no engine version or CHANGELOG bump.

traust's tests/test_default_rule_packs.py runs opengrep test per language, so the new rules are gated there.

#117 is fine as it is for main, which still loads the engine copy.

The traust-standardization skill (/traust-standardization) keeps this kind of placement in sync: it reads the current plans, so it would have pointed this at traust. Please run it when picking up rule-pack work.

@chubirka

Copy link
Copy Markdown
Member Author

Thanks, Shaun. You're right: since traust#291 the default stack on development loads the rule pack from packs/security/detection/opengrep-rules/, so these rules would never run from here. Moved to traust#298: the same 8 typescript/ files (the existing ones were byte-identical, so ssrf.yaml applied cleanly), the README section appended to traust's copy, and no engine version or CHANGELOG bump. A default traust adapters opengrep run from that branch reports the new rules. I also fixed the README's opengrep test path there, which was missing detection/. #117 stays as merged for main. Closing this one. I'll run /traust-standardization before rule-pack work from now on.

🤖 Generated with Claude Code

@chubirka chubirka closed this Oct 28, 2026
@chubirka
chubirka deleted the feat/ts-rules-xss-path-redirect branch October 28, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants