Render User Content Without Running It
Security & Access · security, comments, trust
Updated 2026-08-04
- Treat every piece of user-supplied content as text until proven otherwise. A comment, a display name, a file name, and a profile bio are all places where markup can be typed and then rendered as code for whoever reads the page, which is cross-site scripting.
- Escape on output rather than only cleaning on input. The same value gets rendered in many places, and the one that forgot is the one that runs.
- Decide what formatting a field actually needs before allowing any. Most fields need none, and a display name that supports links is a decision with consequences.
- Restrict the rich text surfaces to a known list of what is allowed rather than a list of what is banned. New ways to smuggle behavior appear constantly, and only the allow list holds.
- Keep uploaded content off your own origin. A file served from your domain runs with your domain's privileges, which is how an avatar becomes a session theft.
- Strip the parts of a link that carry behavior. A user-supplied address should be limited to ordinary web schemes, and anything else should be rendered as plain text.
- Design the states this creates, because the user will hit them:
- Content shown as text when the author expected formatting.
- A pasted link that was not turned into a link.
- An upload refused for its type rather than its size.
- Add a Content Security Policy that tells the browser which scripts are allowed to run. It is the layer that limits the damage when something does slip past the escaping.
Anywhere one person's words are shown to another person is a place where those words can become instructions.
Related guides