git:20260730.db45319 to git:20260820.ee77f46

9 added, 0 removed. Audit A to A.

---
name: dom-vulnerability-static-analysis
description: Static code analysis for DOM-based vulnerabilities in client-side JavaScript -- source/sink enumeration via grep and AST tools, data flow tracing, sanitization assessment, and framework-specific sink detection. Use when performing pre-commit reviews, auditing large codebases without dynamic execution, or triaging minified code for XSS issues.
---
Static analysis framework for DOM XSS -- no dynamic execution needed.
## 1. Enumerate sources and sinks
```bash
# Find all dangerous sinks
rg 'innerHTML|outerHTML|document\.write|insertAdjacentHTML|\.html\(' \
--type js --type ts -n src/
# Find eval-family sinks
rg 'eval\(|new Function\(|setTimeout\([^,]*["\x27]|setInterval\([^,]*["\x27]' \
--type js --type ts -n src/
# Find URL assignment sinks
rg 'location\.(href|assign|replace)\s*=|window\.open\(' \
--type js --type ts -n src/
# Find attacker-controlled sources
rg 'location\.(hash|search|href)|document\.URL|document\.referrer|window\.name|postMessage' \
--type js --type ts -n src/
+ # Weak origin validation (substring/prefix/suffix/loose equality).
+ # The [^=] at the end excludes safe strict === / !== comparisons.
+ rg 'origin\s*\.\s*(indexOf|includes|search|startsWith|endsWith)|origin\s*[!=]=[^=]' \
+ --type js --type ts -n src/
+
# Framework-specific sinks
rg 'dangerouslySetInnerHTML|v-html|ng-bind-html|\[innerHTML\]|hx-get|hx-post' \
--type js --type html -g "*.vue" -g "*.tsx" -n src/
```
**Checkpoint:** Record total sink count and source count. If sinks > 50, prioritize by category (eval-family first, then innerHTML, then URL assignment).
## 2. Trace data flow (source -> sink)
For each sink hit, trace backwards to determine if attacker input reaches it:
```bash
# Find the variable assigned to the sink, then trace its origin
# Example: el.innerHTML = content -- where does `content` come from?
rg "content\s*=" --type js -n src/ | rg -i "location|param|query|hash|input|request"
```
Classify each finding:
- **Direct flow**: source -> sink with no sanitization = **vulnerability**
- **Sanitized flow**: source -> sanitizer -> sink = check sanitizer adequacy
- **Static content**: hardcoded string -> sink = **not exploitable**
## 3. Assess sanitization
```bash
# Find DOMPurify usage
rg "DOMPurify|dompurify|sanitize\(" --type js --type ts -n src/
# Find custom sanitizers (WARNING: verify implementation before trusting)
rg "function.*(sanitiz|escape|clean|filter)" --type js --type ts -n src/
```
For custom sanitizers: apply the `custom-sanitizer-audit` skill (Five-Point Checklist).
For DOMPurify: check version and config -- see `dompurify-mxss-bypass` skill.
**Checkpoint:** For each custom sanitizer found, read the implementation. A function named `escapeHTML` that is NOT a standard library must be reviewed for bypass potential before marking flows through it as safe.
## 4. AST-based analysis (large codebases)
`rg` patterns are fragile for code constructs โ€” they miss variations in whitespace, nesting, and comments. Use AST-based tools for structural matching.
### ast-grep (installed in runtime)
ast-grep uses tree-sitter for structural code matching. Patterns use real code syntax with `$VAR` wildcards โ€” far more accurate than regex for function calls, assignments, and nested expressions.
```bash
# innerHTML / outerHTML sinks โ€” catches any receiver expression
ast-grep -p '$EL.innerHTML = $VAR' -l js src/
ast-grep -p '$EL.outerHTML = $VAR' -l js src/
# insertAdjacentHTML
ast-grep -p '$EL.insertAdjacentHTML($POS, $CONTENT)' -l js src/
# eval-family sinks
ast-grep -p 'eval($INPUT)' -l js src/
ast-grep -p 'new Function($BODY)' -l js src/
# URL assignment sinks
ast-grep -p 'location.href = $VAR' -l js src/
ast-grep -p 'location.assign($URL)' -l js src/
ast-grep -p 'window.open($TARGET)' -l js src/
# postMessage handlers (multi-line aware)
ast-grep -p 'window.addEventListener("message", $HANDLER)' -l js src/
+
+ # ...plus the two registration surfaces that pattern does NOT match
+ ast-grep -p 'window.onmessage = $HANDLER' -l js src/
+ ast-grep -p '$PORT.onmessage = $HANDLER' -l js src/ # MessageChannel / Worker
# React dangerouslySetInnerHTML
ast-grep -p 'dangerouslySetInnerHTML={{$VAR}}' -l tsx src/
# jQuery .html() sink
ast-grep -p '$EL.html($CONTENT)' -l js src/
```
Add `--json` to any command for structured output with file paths, line/column positions, and captured metavariable values. This is useful for programmatic triage or feeding results into jxscout custom analyzers.
### Additional AST tools (if operator-installed)
- **Semgrep**: `semgrep --config p/javascript` for DOM XSS rules (includes taint tracking in Pro)
- **CodeQL**: `javascript/ql/src/Security/CWE-079` for data-flow taint analysis
- **ESLint**: `no-unsanitized/property`, `no-unsanitized/method`
## 5. Report findings
For each confirmed source-to-sink flow:
- File, line number, sink type
- Source of attacker input
- Sanitization present (yes/no, adequate/inadequate)
- Exploitability assessment
- Recommended fix
## Chain With
- `dom-vulnerability-detection` (dynamic analysis), `csp-bypass` (CSP blocks), `custom-sanitizer-audit` (homegrown sanitizer), `dompurify-mxss-bypass` (DOMPurify)