CWE-80: XSS (Basic)
Overview
This guidance helps you interpret and remediate findings from DAST (Dynamic Application Security Testing) tools. The scanner detected that the application reflected user input containing basic XSS vectors (HTML tags with executable content) into web pages without proper neutralization, allowing script execution in victims' browsers. DAST tools identify this by:
Detection Methods:
- Script Tag Injection: Submitting
<script>alert(1)</script>,<script>alert(document.domain)</script> - Event Handler Injection: Testing
<img src=x onerror=alert(1)>,<body onload=alert(1)>,<svg onload=alert(1)> - Iframe/Object Injection: Injecting
<iframe src=javascript:alert(1)>,<object data=javascript:alert(1)> - Callback Detection: Using scanner-specific payloads that trigger HTTP requests to scanner infrastructure when executed
- DOM Inspection: Automated browser testing to verify actual script execution in rendered page
- Response Analysis: Searching for verbatim reflection of payloads in HTML context without encoding
HTTP Evidence:
- Scanner payloads appearing unescaped in HTML response bodies (
<script>alert(ZAP)</script>inview-source:) - HTTP callbacks to scanner infrastructure (Burp Collaborator:
<script src=https://burpcollaborator.net/xss></script>) - Reflected input within HTML tags without HTML entity encoding (
<not converted to<) - Response headers lacking XSS protection (missing or disabled
X-XSS-Protection, weak CSP) - JavaScript execution observable through automated browser instrumentation (Selenium, Playwright)
- Variation in response when dangerous characters (
<,>,",') are submitted vs. safe characters
Scanner Behavior: OWASP ZAP (XSS Reflected, Persistent rules 40012-40017) and PortSwigger Burp Scanner inject polyglot XSS payloads, context-specific vectors, and callback-based probes. Modern scanners use headless browsers to verify actual JavaScript execution, not just payload reflection. They test reflected (non-persistent) and stored (persistent) XSS across all input vectors including URL parameters, POST bodies, headers (User-Agent, Referer), and JSON/XML data.
Analyzing the Dynamic Scan Result
What the DAST Scanner Found
When reviewing your security scan results, you'll see:
HTTP Request Details
- URL and endpoint that triggered the finding
- HTTP method (GET, POST, etc.)
- Query parameters or form data with test payloads
- Request headers and body content
HTTP Response Evidence
- Response showing the vulnerability manifestation
- Evidence of improper handling or injection
- Runtime behavior indicators
Attack Vector
- Which parameter or input is vulnerable
- Type of exploitation possible
- Context where the vulnerability appears
Mapping DAST Findings to Source Code
Find the Vulnerable Endpoint
Use the HTTP request URL to locate the code:
# Search for output/rendering code
grep -r "render" src/
grep -r "innerHTML" src/
grep -r "echo" src/
grep -r "print" src/
Locate Output Generation
Common patterns to search for:
- Reflected XSS: URL parameters echoed in response
- Stored XSS: Database content rendered without escaping
- DOM XSS: JavaScript manipulating DOM with user input
- Template rendering: Unsafe variable interpolation
Find Unescaped Output
Search for rendering code:
# Find output operations
grep -r "innerHTML.*param" src/
grep -r "echo.*GET" src/
grep -r "safe.*False" src/
grep -r "dangerouslySetInnerHTML" src/
Trace to Vulnerable Operation
Look for XSS vulnerabilities:
- Reflected XSS:
?search=<script>alert(1)</script>echoed - Stored XSS: Comment field stored and rendered unescaped
- DOM XSS:
innerHTML = location.hash - Template XSS:
{{ user_input | safe }}in Jinja - JavaScript context: User input in
<script>tags
Remediation
Core principle: Never include untrusted input in HTML output without context-appropriate output encoding so it cannot be interpreted as executable markup or script.
→ For comprehensive remediation guidance, see Static CWE-80 Guidance
Language-Specific Guidance
The static guidance provides detailed remediation steps for many languages. If you need language-specific examples:
Verification and Follow-Up Testing
After applying the fix:
Reproduce the Vulnerability
# Test reflected XSS
curl "http://localhost/search?q=<script>alert(1)</script>"
curl "http://localhost/user?name=<img src=x onerror=alert(1)>"
# Check if payload is reflected unescaped
Verify the Fix
- Confirm all user input HTML-escaped
- Verify output encoding at the sink; input validation alone is insufficient for XSS.
- Verify Content-Security-Policy is present as defense-in-depth, not as a replacement for output encoding.
- Check template auto-escaping enabled
- Ensure JavaScript context properly escaped
- Test that XSS payloads are neutralized
Test Edge Cases
// JavaScript context
'; alert(1)//
"); alert(1)//
// Filter bypasses
<scr<script>ipt>alert(1)</scr</script>ipt>
<img src="x" onerror="alert(1)">
// Or use browser DevTools Network tab to copy as cURL
Re-run DAST Scanner
Run your dynamic scanner again on the fixed endpoint to confirm remediation.