Preventing XSS: Best Practices for Frontend Developers

Blog

Posted by Nuno Marques on 5 Mar 2025

Preventing XSS: Best Practices for Frontend Developers

Introduction

Cross-Site Scripting (XSS) is one of the most common security vulnerabilities in web applications. It allows attackers to inject malicious scripts into a website, which can steal data, hijack sessions, or perform other harmful actions. As a frontend developer, it's crucial to understand how to prevent XSS attacks and protect your users.

In this guide, we’ll break down XSS types, how they work, and the best practices to prevent them.

Estimated reading time: 7 minutes


Understanding XSS Attacks

XSS attacks occur when an application fails to properly sanitize user input, allowing malicious scripts to execute in the browser.

Types of XSS Attacks

  • Stored XSS: Malicious script is permanently stored on the server and served to users.
  • Reflected XSS: Script is injected via a URL parameter and executed when the link is clicked.
  • DOM-based XSS: Malicious script is executed by modifying the webpage's DOM dynamically.

Example of a Reflected XSS Attack

<!-- Vulnerable input field -->
<input id="userInput" type="text">
<button onclick="document.write(userInput.value)">Submit</button>

If an attacker enters <script>alert('XSS Attack!')</script>, the browser will execute the script instead of treating it as text.


Best Practices to Prevent XSS

1. Sanitize User Input

Use a library like DOMPurify to clean user-generated content.

import DOMPurify from 'dompurify';
const safeHTML = DOMPurify.sanitize(userInput);
document.getElementById("content").innerHTML = safeHTML;

2. Escape Output in HTML, JavaScript, and URLs

  • Use textContent instead of innerHTML to prevent script execution.
document.getElementById("output").textContent = userInput;
  • Escape dynamic URLs using encodeURI().
const safeURL = encodeURI(userInput);
window.location.href = safeURL;

3. Use Content Security Policy (CSP)

CSP restricts the sources from which scripts can be loaded, preventing injected scripts from executing.

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">  

4. Avoid Inline JavaScript

Never use inline event handlers like onclick="alert('XSS!')". Instead, use event listeners.

document.getElementById("btn").addEventListener("click", () => alert("Safe click"));

5. Validate and Sanitize Server-Side

  • Always validate input using a strict schema (e.g., Joi in Node.js).
const Joi = require("joi");
const schema = Joi.string().max(100).pattern(/^[a-zA-Z0-9]+$/);
  • Sanitize database queries to prevent stored XSS.

6. Use Secure Cookies for Authentication

Storing authentication tokens in Local Storage is risky. Use HttpOnly Secure Cookies instead (Read: How to Secure Your Node.js API with JWT and Cookies).


Key Takeaways

  • Sanitize all user input before rendering it on the page.
  • Escape dynamic content to prevent script execution.
  • Implement a Content Security Policy (CSP) to block unauthorized scripts.
  • Avoid inline JavaScript to reduce script injection risks.
  • Use Secure Cookies instead of Local Storage for authentication tokens.

Next Steps

  • Implement strict input validation on both frontend and backend.
  • Use security-focused frameworks like Helmet.js to enforce best practices.
  • Regularly audit and test your app for XSS vulnerabilities.

Related Articles