git:20260528.f3e4348 to git:20260529.8f6ea0e
29 added, 48 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.
+ 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.
+ Static analysis framework for DOM XSS -- no dynamic execution needed.
## 1. Enumerate sources and sinks
```bash
# Find all dangerous sinks
- grep -rn 'innerHTML\|outerHTML\|document\.write\|insertAdjacentHTML\|\.html(' \
- --include="*.js" --include="*.jsx" --include="*.ts" --include="*.tsx" src/
+ rg 'innerHTML|outerHTML|document\.write|insertAdjacentHTML|\.html\(' \
+ --type js --type ts -n src/
# Find eval-family sinks
- grep -rn 'eval(\|new Function(\|setTimeout([^,]*["\x27]\|setInterval([^,]*["\x27]' \
- --include="*.js" --include="*.ts" src/
+ rg 'eval\(|new Function\(|setTimeout\([^,]*["\x27]|setInterval\([^,]*["\x27]' \
+ --type js --type ts -n src/
# Find URL assignment sinks
- grep -rn 'location\.\(href\|assign\|replace\)\s*=\|window\.open(' \
- --include="*.js" --include="*.ts" src/
+ rg 'location\.(href|assign|replace)\s*=|window\.open\(' \
+ --type js --type ts -n src/
# Find attacker-controlled sources
- grep -rn 'location\.\(hash\|search\|href\)\|document\.URL\|document\.referrer\|window\.name\|postMessage' \
- --include="*.js" --include="*.ts" src/
+ rg 'location\.(hash|search|href)|document\.URL|document\.referrer|window\.name|postMessage' \
+ --type js --type ts -n src/
# Framework-specific sinks
- grep -rn 'dangerouslySetInnerHTML\|v-html\|ng-bind-html\|\[innerHTML\]\|hx-get\|hx-post' \
- --include="*.js" --include="*.tsx" --include="*.html" --include="*.vue" src/
-
- # AngularJS CSTI: user input bound to scope then evaluated in {{ }} templates
- # Payload: {{constructor.constructor('alert(1)')()}} (sandbox escape for AngularJS 1.x)
- grep -rn 'ng-app\|ng-bind\|\$scope\.\|ng-model\|ng-bind-html' \
- --include="*.html" --include="*.js" src/
-
- # Prototype pollution sources: Object.assign/spread with user-controlled input
- grep -rn 'Object\.assign\|\.\.\..*param\|\.\.\..*query\|merge(' \
- --include="*.js" --include="*.ts" src/
+ rg 'dangerouslySetInnerHTML|v-html|ng-bind-html|\[innerHTML\]|hx-get|hx-post' \
+ --type js --type html -g "*.vue" -g "*.tsx" -n src/
```
- ## 2. Trace data flow (source → sink)
+ **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?
- grep -rn "content\s*=" --include="*.js" src/ | grep -i "location\|param\|query\|hash\|input\|request"
+ # 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**
+ - **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
- grep -rn "DOMPurify\|dompurify\|sanitize(" --include="*.js" --include="*.ts" src/
+ rg "DOMPurify|dompurify|sanitize\(" --type js --type ts -n src/
- # Find custom sanitizers
- grep -rn "function.*sanitiz\|function.*escape\|function.*clean\|function.*filter" \
- --include="*.js" --include="*.ts" 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.
+ For DOMPurify: check version and config -- see `dompurify-mxss-bypass` skill.
- ## 4. AST-based analysis (optional)
+ **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.
- For large codebases, use tooling:
+ ## 4. AST-based analysis (large codebases)
+
- **Semgrep**: `semgrep --config p/javascript` for DOM XSS rules
- **CodeQL**: `javascript/ql/src/Security/CWE-079` for taint tracking
- **ESLint**: `no-unsanitized/property`, `no-unsanitized/method`
- ## 5. Cross-validate findings
-
- Before reporting, reduce false positives by cross-referencing:
- - Compare grep-based sink hits (steps 1-2) against AST taint-tracking results (step 4) — a finding confirmed by both methods is high-confidence
- - For grep-only hits: manually verify the data flow in context (minified code aliasing can produce false matches)
- - For AST-only hits: confirm the sink pattern wasn't missed by grep regex limitations
- - Discard any finding where the source is provably non-attacker-controlled after contextual review
-
- ## 6. Report findings
+ ## 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
- ## 7. Library-specific XSS gadgets
-
- See `GADGETS.md` for jQuery `.text()` re-decoding, moment.js format injection, and `javascript:` URI hostname bypass patterns.
-
## Chain With
- - `dom-vulnerability-detection` (dynamic analysis), `csp-bypass` (CSP blocks), `dompurify-mxss-bypass` (DOMPurify), `aem-sling-exploitation` (AEM-specific XSS gadgets)
+ - `dom-vulnerability-detection` (dynamic analysis), `csp-bypass` (CSP blocks), `custom-sanitizer-audit` (homegrown sanitizer), `dompurify-mxss-bypass` (DOMPurify)