Cross-site scripting in HTML template strings

Cross-site scripting in HTML template strings

Description

Cross-site scripting (XSS) can occur when user input is inserted into an HTML template string without suitable encoding. An attacker can supply markup or scripts that run in another user's browser, exposing information or compromising a session.

Potential impact

  • Scripts may steal accessible cookies, session tokens or information entered on the page.
  • Injected HTML or scripts may alter the page, disrupt its behavior or present phishing content.

Remediation

  • When inserting text into an HTML body, use HTML encoding for that context or the template engine's automatic escaping.
  • If markup is unnecessary, use textContent instead of innerHTML. Use setAttribute only with fixed, non-executable attribute names; validate URL schemes and destinations separately.
  • If HTML markup must be allowed, restrict tags and attributes with an HTML sanitizer such as DOMPurify. Sanitization differs from text encoding, and ordinary HTML escaping must not be reused for JavaScript or CSS contexts.

Examples

Before

javascript
const userInput = '<img src="x" onerror="alert(1)">'; // Malicious input
const message = `<div>${userInput}</div>`;
document.body.innerHTML = message;

After

javascript
function escapeHtml(str) {
  return str.replace(/[&<>'"]/g, function (c) {
    return {
      "&": "&amp;",
      "<": "&lt;",
      ">": "&gt;",
      "'": "&#39;",
      '"': "&quot;",
    }[c];
  });
}
const userInput = '<img src="x" onerror="alert(1)">'; // Malicious input
const message = `<div>${escapeHtml(userInput)}</div>`;
document.body.innerHTML = message;

Explanation:

  • Before: The markup in userInput is inserted directly into HTML and may execute in the browser.
  • After: escapeHtml encodes the input for the HTML body in this example, so the supplied tags are displayed as text.

References