-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
163: Avoiding Cross-Site Scripting in Client Code
Wait, how can a simple string of text actually run code on my page?
It happens because of how the browser interprets HTML. If you use .innerHTML to push data from a user—say, a username or a bio—directly into the DOM, you're telling the browser: "Take this string and parse it as HTML."
I've seen this happen in production way too often. Imagine you have a user profile page. You fetch the user's bio from an API and do this:
const userBio = "I love coding!
";
document.getElementById('bio-display').innerHTML = userBio;
The browser sees the <img> tag, fails to find the image at source "x", and immediately fires the onerror event. Just like that, the attacker is running arbitrary JavaScript in your user's browser. They aren't just popping up alerts; they could be stealing session tokens or redirecting your users to a phishing site.
Is there a safer way to put text on the screen without risking this?
Absolutely. In 90% of cases, you don't actually need to render HTML; you just want to show text. The gold standard here is .textContent.
When you use .textContent, the browser doesn't try to parse the string. It treats everything as a literal string of characters. If a user tries to inject a <script> tag, the page will literally display the characters "<script>" on the screen rather than executing them.
const userBio = "I love coding! <img src=x onerror=alert('Hacked!')>";
// This is the safe way
document.getElementById('bio-display').textContent = userBio;
I always tell my juniors: treat .innerHTML as a "red flag" property. If you see it in a code review, ask yourself: "Do we really need to render HTML here, or could .textContent do the job?"
What happens if I actually need to allow some HTML, like bold or italics?
This is where things get tricky. Sometimes you're building a CMS or a comment section where you want to allow <b> or <i> tags, but obviously not <script> or <iframe>.
Don't try to write your own Regular Expression to "clean" the string. Trust me on this—attackers are much more creative than your Regex will be. They'll find a way around your filter using encoding or weird attribute combinations.
Instead, use a dedicated sanitization library like DOMPurify. It takes a dirty string and returns a clean one based on a strictly defined whitelist of safe tags and attributes.
import DOMPurify from 'dompurify';
const dirtyHtml = '<img src=x onerror=alert(1)> <b>Hello!</b>';
const cleanHtml = DOMPurify.sanitize(dirtyHtml);
// Now it's safe to use innerHTML because the dangerous parts are stripped out
document.getElementById('comment-body').innerHTML = cleanHtml;
// Result: <b>Hello!</b> (The img tag is gone)
It's a small dependency, but it saves you from a massive security headache.
📋 Practical Task
Securing the User Comment Feed
You are working on a community forum. There is a bug where users can execute scripts by posting comments. You have been given a piece of vulnerable code that uses .innerHTML to render comments from an array.
Your Task:
- Create an HTML file with a
<div id="comment-list">. - Create a JavaScript array of "comments" where at least one comment contains a malicious payload (e.g.,
<img src=x onerror="alert('XSS!')">). - Write a function that loops through the comments and appends them to the
#comment-list. - Initially, implement it using
.innerHTMLto confirm the vulnerability (you'll see the alert fire). - Then, refactor the code to use
.textContent(ordocument.createElement('p')with.textContent) to ensure that the malicious payload is rendered as harmless text.
There are no comments for now.