Cross-Site Scripting: Contexts, Safe Sinks and Boundaries

Cross-site scripting occurs when attacker-controlled content becomes executable in a user's browser under a site's origin.

Author
absequ
Published
Updated
Category
Security
  • xss
  • security
  • practical guide

Cross-site scripting occurs when attacker-controlled content becomes executable in a user's browser under a site's origin. The entry point might be a stored comment, a reflected query value or a client-side DOM update. The important question is not simply whether input contains angle brackets, but where that input is eventually interpreted.

The mental model

Browsers interpret HTML text, attribute values, URLs, JavaScript and CSS in different contexts. Escaping suitable for a text node is not a universal solution for every context. A string that is harmless as visible text can become dangerous when treated as a script or inserted into an event-handler attribute.

Framework text interpolation normally provides a safe way to display plain text, but escape hatches still matter. Raw HTML insertion, direct DOM sinks and unsafe URL handling can bypass that protection. Rich-text editors need an explicit policy for supported markup; a code-example string should remain a string rather than being executed to show its result.

A practical workflow

Trace untrusted values from their source to their final sink. Prefer a text-only sink when markup is unnecessary. When limited HTML is a product requirement, use a maintained sanitizer configured for that purpose and keep it updated. Do not replace a sanitizer with a regular expression that attempts to enumerate every dangerous tag.

The example uses textContent because the intended result is a label, not HTML. A real component should also validate links separately and keep user-controlled strings out of executable configuration. Validation, safe output handling and authorization address different boundaries and should not be collapsed into one generic cleaning function.

Worked example

Cross-Site Scripting: Contexts, Safe Sinks and Boundaries — example
const label = document.createElement('p');
const untrustedName = '<img src=x onerror=alert(1)>';
label.textContent = untrustedName;
document.body.append(label);
// The characters are displayed as text, not parsed as a new image element.
// Do not replace this assignment with innerHTML for ordinary text.

Test what the browser actually creates, not whether a particular substring was removed. For this label, the invariant is that no attacker-provided element or event handler appears in the DOM. Include quotation marks, Unicode and long input in tests, while keeping payloads inside a controlled local fixture.

Stored content deserves the same scrutiny as query parameters. Data from your own database may originally have come from another user or an imported feed. A database read is not evidence that the value is trustworthy. Apply output handling at the rendering boundary where the actual context is known.

Failure modes and security

CSP and Trusted Types can add protection around dangerous execution paths, but they do not excuse unsafe rendering. Avoid logging a full malicious payload when it may contain user data or credentials. Prefer a sanitized finding description and a minimal synthetic reproduction.

A URL beginning with a surprising scheme can be unsafe even if it contains no HTML. Use an explicit URL policy for links and media, reject embedded credentials and avoid accepting arbitrary React components or executable styles in content JSON. Keep code examples inert, including examples that discuss attacks.

Practice and verification

Create a local comment card with a plain-text body and a separately validated source link. Verify that markup-like input stays visible as text, unsafe link schemes are rejected and long content cannot break the layout. Then identify every raw-HTML escape hatch in the application and justify why each exists. If none is required, remove the capability rather than maintaining a complex allowlist for unused features.

References

absequ

Building practical and scalable solutions across software, hiring, and technology education.

info@absequ.com
© 2026 Abstract Equations Tech Private Limited. All rights reserved.absequ™ is a brand of Abstract Equations Tech Private Limited, India.

Allow analytics cookies to help us understand site usage? Essential site features work with either choice. Privacy Policy.