针对 JavaScript/TypeScript、React、Vue 等的 XSS 静态漏洞扫描器(OWASP A03:2021),可检测反射、存储和 DOM 型 XSS。
Scans source code for Cross-Site Scripting (XSS) vulnerabilities across 10 checks covering server-side rendering, client-side DOM manipulation, and framework-specific patterns. Maps to OWASP A03:2021 — Injection and CWE-79.
bash
# Scan entire project
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py .
# Scan single file
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py src/components/Post.tsx
# CI mode — exits 1 on any CRITICAL or HIGH finding
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py . --ci
# JSON output (for SARIF pipelines)
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py . --format json
# GitHub Actions annotations
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py . --format github
# Run only one check
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py . --check XV003
IDSeverityTitleCWELanguagesXV001HIGHinnerHTML / outerHTML with user dataCWE-79JS/TS/Vue/HTMLXV002HIGHdocument.write() with user dataCWE-79JS/TS/HTMLXV003CRITICALeval() / setTimeout(string) with user dataCWE-95JS/TS/VueXV004HIGHdangerouslySetInnerHTML without DOMPurifyCWE-79React JSX/TSXXV005CRITICALDjango mark_safe() / autoescape offCWE-79Python/HTMLXV006CRITICALJinja2 | safe filter or Markup() bypassCWE-79Python/HTMLXV007HIGHPHP echo/print without htmlspecialcharsCWE-79PHPXV008HIGHERB raw / html_safe without sanitizeCWE-79Ruby/ERBXV009HIGHVue v-html with dynamic expressionCWE-79VueXV010HIGHAngular bypassSecurityTrust / Go template.HTML castCWE-79TS/Go
element.innerHTML = or .html() (jQuery) where user-controlled data ( req.query, req.body, request.GET, location.search, etc.) flows in within ±20 lines, and no DOMPurify.sanitize() guard nearby.DOMPurify.sanitize(input) before assignment, or data source is internal/static only.document.write() or document.writeln() with user-controlled data in nearby lines.document.write() only writes developer-controlled static strings (no user input path).eval(userVar), setTimeout(userVar + "..."), or new Function(...) with user data in the argument. Skipped in test/spec files.eval() used only with static strings (JSON schemas, etc.), or user data passed via safe JSON.parse().dangerouslySetInnerHTML={{ __html: ... }} without DOMPurify.sanitize() wrapping the value within 5 lines.DOMPurify.sanitize(html) — pattern DOMPurify.sanitize( appears within ±5 lines.mark_safe(user_data) where user-controlled data flows in ±10 lines. Also fires on {% autoescape off %} in any template.mark_safe() only wraps developer-defined static HTML strings, or data is sanitized with bleach.clean() first.| safe or wrapped in Markup() when user-controlled data is nearby within ±10 lines.| safe used only on developer-controlled content (e.g., static site generator output with no user input).echo $_GET['key'] or echo $var without htmlspecialchars() / htmlentities() / strip_tags() / filter_input() on the same line.htmlspecialchars($var, ENT_QUOTES, 'UTF-8') before output.<%== user_var %>, user_var.html_safe, or raw user_var in ERB templates where user input flows in ±10 lines, with no sanitize() or strip_tags() guard nearby.h(var) / escape_html(), or sanitize() wraps the user value.v-html="someVar" where the value is dynamic and no DOMPurify.sanitize() appears in the surrounding 10 lines.DOMPurify.sanitize(rawHtml) before being bound to v-html.bypassSecurityTrustHtml(userVar) or bypassSecurityTrustScript(userVar) where user data flows nearby. Go: template.HTML(userStr) or template.JS(userStr) cast with user-controlled input.[innerHTML] binding. Go — let html/template handle escaping automatically (never cast user strings to template.HTML).XSS TypeChecksReflected XSSXV001, XV002, XV005, XV006, XV007Stored XSSXV001, XV004, XV008, XV009DOM-based XSSXV001, XV002, XV003Server-Side Template Injection → XSSXV005, XV006Framework bypass XSSXV004, XV009, XV010
LanguageFrameworkChecksJavaScript / TypeScriptVanilla, React, Vue, AngularXV001–XV004, XV009, XV010PythonDjango, Jinja2 (Flask/FastAPI)XV005, XV006PHPVanilla, WordPressXV007RubyRails, SinatraXV008Gohtml/template, GinXV010
The scanner considers a value "user-controlled" if the surrounding ±15-20 lines contain:
text
req.query / req.body / req.params / req.headers (Node.js/Express)
request.GET / request.POST / request.args / request.json (Django/Flask)
params[ / query_params[ / @query_params (Rails/FastAPI)
$_GET[ / $_POST[ / $_REQUEST[ / $_COOKIE[ (PHP)
location.search / location.hash / URLSearchParams( (Browser DOM)
c.Query( / c.Param( / r.URL.Query( (Go Gin/stdlib)
These patterns near a sink suppress the finding:
GuardContextDOMPurify.sanitize(DOM XSS in JS/TS/Vuesanitize_html(Python bleach-basedbleach.clean(Python Djangohtmlspecialchars(PHPhtmlentities(PHPh( / html_escape(Rails ERBsanitize(Rails, Vuexss.filterXSS(Node.js xss libraryescape(Variousstrip_tags(PHP / Rails
yaml
# GitHub Actions
- name: XSS audit
run: python3 scripts/xss_audit.py . --format github --ci
# GitLab CI
xss-audit:
script:
- python3 scripts/xss_audit.py . --ci
allow_failure: false
bash
# Pre-commit hook
#!/bin/sh
python3 ~/.claude/skills/phy-xss-audit/scripts/xss_audit.py . --ci
text
======================================================================
phy-xss-audit — XSS Vulnerability Report
======================================================================
Total: 3 | Critical: 1 | High: 2
======================================================================
🔴 [XV005] CRITICAL — Django mark_safe() / autoescape off (CWE-79)
File : app/views.py:47
Code : return mark_safe(request.GET.get('content', ''))
Fix : Never call mark_safe() on user input. Use bleach.clean() first.
🟠 [XV001] HIGH — innerHTML / outerHTML with user data (CWE-79)
File : src/components/Comment.tsx:23
Code : el.innerHTML = comment.body
Fix : Sanitize with DOMPurify.sanitize(userInput) before innerHTML.
🟠 [XV004] HIGH — dangerouslySetInnerHTML without DOMPurify (CWE-79)
File : src/components/Post.jsx:61
Code : dangerouslySetInnerHTML={{ __html: post.content }}
Fix : dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(post.content) }}
This skill covers OWASP A03:2021 — Injection (XSS vector).
OWASP IDDescriptionChecksA03:2021Injection — Cross-Site ScriptingXV001–XV010
phy- suite OWASP coverage after this skill:
Full OWASP Top 10 coverage achieved.
SkillRelationshipphy-cors-auditCORS misconfig → OWASP A04phy-session-auditCookie/session security → OWASP A07phy-ssrf-auditServer-side request forgery → OWASP A10phy-crypto-auditWeak cryptography → OWASP A02phy-security-headersMissing CSP headers that mitigate XSS
re, pathlib, argparse, json).git/, node_modules/, __pycache__/, dist/, build/, .venv/utf-8 first, falls back to latin-1*.test.js / *.spec.ts to reduce test utility false positivesCanlah AI — Run performance marketing without breaking your brand.