dom-vulnerability-static-analysis · git:20260529.8f6ea0e · 2026-05-29 · sha256 d1c9673cbd0fed48

dom-vulnerability-static-analysis git:20260529.8f6ea0eA

Immutable. This exact content is served forever at /api/v1/blob/d1c9673cbd0fed48.

---
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/

# 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)

- **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. 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)