Prevent cross-site scripting by encoding output for its exact sink, keeping template autoescaping on, and backing it with a strict Content Security Policy. Use when rendering user-controlled data into HTML, attributes, JavaScript, or URLs.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add Amey-Thakur/AI-SKILLS --skill xss-defense --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Xss Defense?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/amey-thakur-xss-defense)More formats (shields.io, HTML) on the badges page.
---
name: xss-defense
description: Prevent cross-site scripting by encoding output for its exact sink, keeping template autoescaping on, and backing it with a strict Content Security Policy. Use when rendering user-controlled data into HTML, attributes, JavaScript, or URLs.
---
# XSS defense
Cross-site scripting happens when data the user controls is interpreted as
code by another user's browser. The defense is contextual output encoding:
the same string is safe in HTML text and dangerous in a `<script>` block, so
encoding depends on where the value lands. Autoescaping and a Content
Security Policy backstop the encoding you forget.
## Method
1. **Encode at output, for the specific context.** HTML body needs
HTML-entity encoding; an attribute needs attribute encoding; inside
`<script>` needs JavaScript-string encoding; a URL needs
percent-encoding. Encoding for the wrong context still lets script
through. Encode when you write to the page, not when you store.
2. **Keep template autoescaping on and never bypass it blindly.** Jinja2,
Django, React (`{}`), and Handlebars escape HTML by default. Audit every
bypass: `|safe`, `mark_safe`, `dangerouslySetInnerHTML`, `v-html`,
`{{{ }}}`. Each is a place you promised the value is already safe. Make
sure that promise holds.
3. **Sanitize rich HTML with a real library, not a regex.** If users
legitimately submit HTML from a rich-text editor, run it through
DOMPurify or a server-side equivalent with a strict tag and attribute
allowlist. Regex stripping of `<script>` is trivially bypassed with
`<img onerror>` and malformed tags.
4. **Guard URL sinks against `javascript:` schemes.** A user-supplied
`href` or `src` of `javascript:alert(1)` executes on click. After
canonicalizing, allow only `http`, `https`, and `mailto`; reject or
neutralize the rest.
5. **Deploy a strict Content Security Policy.** Set
`Content-Security-Policy` with a nonce- or hash-based `script-src`, no
`unsafe-inline`, and no broad wildcards. CSP turns a missed encoding from
account takeover into a blocked script and a console error. Start in
`Content-Security-Policy-Report-Only` to find violations before you
enforce.
6. **Set session cookies HttpOnly so script cannot read them.** Mark them
`HttpOnly` and `Secure`. Even if XSS fires, the token stays out of reach
of `document.cookie`, shrinking what a successful injection can steal.
## Signals
- Can you name the output context (HTML, attribute, JS, URL) for every place
user data reaches the page?
- Does a grep for `dangerouslySetInnerHTML`, `|safe`, and `v-html` turn up
only reviewed, justified uses?
- Does your CSP block inline script, tested against a real injection
payload?
## Boundaries
Output encoding defends against XSS; it is not input validation and does not
stop injection into other sinks. DOM-based XSS lives entirely in client
JavaScript (`innerHTML`, `eval`, `document.write`) and needs the same
contextual encoding applied in the browser. Framework defaults cover most
cases, so reach for manual encoding only where you left autoescaping behind.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!