Skip to content

User-supplied profile bios render unescaped, and one contains a `<script>` tag. What's the correct fix?

Short answer

Stored XSS is fixed by encoding data for the exact context where it's rendered (HTML body, attribute, JavaScript, URL) so the browser treats it as text, with a Content-Security-Policy as a second layer. Blacklisting the word 'script' is trivially bypassed via event handlers, mixed case, and encodings. You can't make your users disable JavaScript. Asking users not to enter HTML isn't an enforceable control. Encode on output, every time you render.

The bio is stored and later rendered into a page without being encoded, so a <script> tag in it executes in every viewer's browser. That's stored (persistent) cross-site scripting — one injected payload hits every user who loads the profile. The root cause is data being interpreted as markup at render time.

The correct fix: context-aware output encoding

XSS is a rendering problem, so fix it where the data meets the page: encode on output, for the specific context.

  • In HTML body context, encode <, >, &, etc., so the browser shows the text instead of parsing a tag.
  • In an HTML attribute, JavaScript, or URL context, the correct encoding differs — using the wrong one still leaves a hole.

Modern frameworks auto-escape by default; the bug usually appears where someone reaches for a raw-HTML escape hatch. Add a Content-Security-Policy as defense-in-depth so that even if an encoding is missed, inline and untrusted scripts are blocked.

Why the distractors are wrong

  • Stripping the word 'script' is input blacklisting and trivially bypassed: an img tag with an onerror handler, an svg tag with onload, mixed case, HTML entities, and dozens of other vectors carry no literal "script".
  • Telling users to disable JavaScript is absurd as a control — you don't run your users' browsers, and the app depends on JS anyway.
  • Asking users not to enter HTML is a request, not an enforcement; the attacker simply ignores it.

What the interviewer is probing

Whether you know XSS is fixed on output, in the right context, not by filtering inputs against a denylist, and whether you layer a CSP on top without mistaking it for the primary fix. Strong candidates note that input validation and trusted HTML sanitization have their place (for rich-text fields), but contextual output encoding is the dependable, universal control.

Likely follow-ups

  • Why is output encoding context-dependent — how does encoding for an HTML attribute differ from a JS string?
  • What does a Content-Security-Policy add, and why isn't it a substitute for encoding?
  • When is input sanitization (e.g. an HTML sanitizer) appropriate instead of encoding?

Sources

Get 100 cybersecurity interview questions + answers

Drop your email and we'll send you the free PDF pack and the flashcard deck.

No spam. Unsubscribe anytime.