Help us improve
Share bugs, ideas, or general feedback.
From xss-prevention
Prevents XSS attacks via input sanitization, output encoding, CSP headers, DOMPurify, and safe DOM APIs. Use for user-generated content, rich text editors, comments, and dynamic HTML.
npx claudepluginhub secondsky/claude-skills --plugin xss-preventionHow this skill is triggered — by the user, by Claude, or both
Slash command
/xss-prevention:xss-preventionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement comprehensive Cross-Site Scripting attack prevention through input sanitization, output encoding, Content Security Policy headers, and secure coding practices.
Eliminates XSS by context-aware output encoding and content security policies. Trigger when rendering user content in HTML/DOM or building browser-rendered APIs.
Block script injection by encoding output, sanitizing HTML, and enforcing Content Security Policy.
Enforce XSS prevention in React apps: safe JSX binding, sanitizing dangerouslySetInnerHTML with DOMPurify, validating URLs, avoiding SSR concatenation, and escaping preloaded state.
Share bugs, ideas, or general feedback.
Implement comprehensive Cross-Site Scripting attack prevention through input sanitization, output encoding, Content Security Policy headers, and secure coding practices.
| Type | Vector | Defense |
|---|---|---|
| Reflected | URL parameters | Output encoding |
| Stored | Database content | Input sanitization |
| DOM-based | Client-side JS | Safe DOM APIs |
| Mutation | HTML parser quirks | Strict sanitization |
function encodeHTML(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
function encodeForAttribute(str) {
return str.replace(/[^\w.-]/g, char =>
`&#x${char.charCodeAt(0).toString(16)};`
);
}
// Usage in templates
app.get('/profile', (req, res) => {
const username = encodeHTML(req.query.name);
res.send(`<h1>Welcome, ${username}</h1>`);
});
import DOMPurify from 'dompurify';
const config = {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href', 'title'],
ALLOW_DATA_ATTR: false
};
function sanitizeHTML(dirty) {
return DOMPurify.sanitize(dirty, config);
}
// React component
function RichContent({ html }) {
return (
<div dangerouslySetInnerHTML={{ __html: sanitizeHTML(html) }} />
);
}
// Express middleware
app.use((req, res, next) => {
const nonce = crypto.randomBytes(16).toString('base64');
res.locals.nonce = nonce;
res.setHeader('Content-Security-Policy', [
"default-src 'self'",
`script-src 'self' 'nonce-${nonce}'`,
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"connect-src 'self' https://api.example.com",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'"
].join('; '));
next();
});
// DANGEROUS - avoid these
element.innerHTML = userInput; // XSS risk
element.outerHTML = userInput; // XSS risk
document.write(userInput); // XSS risk
eval(userInput); // Code injection
// SAFE - use these instead
element.textContent = userInput; // Escaped automatically
element.setAttribute('data-id', id); // Safe for attributes
document.createTextNode(userInput); // Creates safe text node
function isSafeURL(url) {
try {
const parsed = new URL(url);
return ['http:', 'https:'].includes(parsed.protocol);
} catch {
return false;
}
}
// Usage
const href = isSafeURL(userURL) ? userURL : '#';
Different contexts require different encoding approaches:
Always encode output by the specific context where data will be rendered.
See references/python-sanitization.md for:
See references/nodejs-advanced.md for:
✅ DO:
❌ DON'T: