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

HTML Injection

security CWE-80 OWASP A3:2021 CVSS 6.1 PHP 5.0+ Beginner
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep, psalm, and twig-auto-escape — all specialist/SAST-class tools. The pattern (echo $userInput without htmlspecialchars) is detectable by these tools but not by a default linter or compiler error. Scores d5 exactly.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a single consistent call — htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8') — but common_mistakes show it must be applied across all output points and in context-appropriate ways (HTML vs JSON context), making it a small pattern-replacement refactor rather than a true one-liner. e3 fits: replace pattern with safer alternative across output sites.

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

Closest to 'localised tax' (b3). The term applies only to web contexts (applies_to contexts: web) and the fix is a consistent escaping discipline within template/output layers. It imposes a persistent but bounded hygiene requirement on view/output code, not a cross-cutting architectural concern. b3 is appropriate — one layer pays, rest of codebase is largely unaffected.

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

Closest to 'serious trap' (t7). The canonical misconception is explicitly that 'HTML injection without script execution is harmless' — developers coming from an XSS mental model believe only script execution matters, missing that injected forms and defacement cause real harm. This directly contradicts how many developers reason about injection risk and is worse than a simple edge case, placing it at t7.

About DEBT scoring →

Also Known As

markup injection content injection

TL;DR

Unsanitised user input rendered as raw HTML allows attackers to inject arbitrary markup, defacing pages or phishing users.

Explanation

HTML injection differs from XSS in that it may not execute JavaScript — it injects HTML elements such as forms, links, or images to manipulate page appearance. An attacker can overlay a fake login form onto a legitimate page to harvest credentials, or inject meta-refresh tags to redirect users. The fix is identical to XSS prevention: encode all user-supplied output with htmlspecialchars() before rendering it in HTML context.

Common Misconception

HTML injection without script execution is harmless. Attackers inject convincing fake login forms for in-page phishing, defacement, and misleading content — no JavaScript required for significant impact.

Why It Matters

Injecting HTML can create convincing phishing prompts, fake login forms, or deface pages — even without executing JavaScript, it erodes user trust and enables credential theft.

Common Mistakes

  • Using strip_tags() as the sole defence — it strips tags but not attributes like onload in allowed tags.
  • Reflecting user input into HTML attribute values without proper escaping — quotes can break out of attributes.
  • Confusing HTML injection with XSS — HTML injection that doesn't execute scripts can still be very harmful.
  • Not applying contextual escaping: htmlspecialchars() in HTML context, but JSON encode in script context.

Code Examples

✗ Vulnerable
// User HTML echoed without escaping
echo "<div>Hello \$username</div>";
// username = <h1>HACKED</h1> → injects structure
✓ Fixed
// Always escape output
echo '<div>Hello ' . htmlspecialchars(\$username, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8') . '</div>';

// For rich text — use HTMLPurifier to allow safe HTML only
\$purifier = new HTMLPurifier(HTMLPurifier_Config::createDefault());
\$clean    = \$purifier->purify(\$_POST['bio']);
echo \$clean;

// HTML injection is a stepping stone to XSS
// Even <img src=x onerror=alert(1)> counts as HTML injection

Added 15 Mar 2026
Edited 22 Mar 2026
Views 24
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 2 pings S 0 pings M 0 pings T 0 pings W 3 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 8 Perplexity 3 ChatGPT 3 Google 2 Ahrefs 1 SEMrush 1
crawler 15 crawler_json 3
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
HTML injection that doesn't execute scripts is still dangerous — use htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8') consistently on all output, not just where you think JS is injected
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
echo $userInput without htmlspecialchars; template printing variable without escaping; only escaping for scripts not all HTML output
Auto-detectable: ✓ Yes semgrep psalm twig-auto-escape
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-79 CWE-80

✓ schema.org compliant