关于 xss-prevention
面向 Web 开发者的 XSS 防护技能,介绍输入净化、按上下文输出编码、CSP 和安全 DOM API。适用于展示用户内容及动态生成 HTML 的场景。
主要功能
- 01按上下文编码输出
- 02使用允许列表净化 HTML
- 03配置 CSP 响应头
- 04采用安全 DOM API
- 05验证 URL 协议
适用场景
- 01安全展示用户生成内容
- 02防护评论与富文本编辑器
- 03处理搜索参数和动态 HTML
- 04检查 URL 与脚本注入风险
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill xss-prevention安装后在 Claude Code 中输入/xss-prevention确认已加载。
附带文件references/nodejs-advanced.mdreferences/python-sanitization.md
详细介绍
XSS 防护
概述
通过输入清理、输出编码、Content Security Policy 标头和安全编码实践,全面防范跨站脚本攻击。
适用场景
- 显示用户生成的内容
- 富文本编辑器
- 评论系统
- 搜索功能
- 动态 HTML 生成
- 模板渲染场景
XSS 攻击类型
| 类型 | 攻击向量 | 防御措施 |
|---|---|---|
| 反射型 | URL 参数 | 输出编码 |
| 存储型 | 数据库内容 | 输入清理 |
| 基于 DOM | 客户端 JS | 安全 DOM API |
| 变异型 | HTML 解析器的特殊行为 | 严格清理 |
输出编码(Node.js)
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>`);
});
DOMPurify 清理
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) }} />
);
}
Content Security Policy
// 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();
});
安全 DOM API
❌ 切勿对用户控制的输入执行以下任何操作——这些都是 XSS 接收点,无法以安全的方式将不可信数据传入其中:
- 将其赋给
element.innerHTML/element.outerHTML - 将其传给
eval() - 将其传给
document.write() - 将其作为字符串传给
setTimeout/setInterval - 将其插入内联事件处理程序(例如
onclick="...")
// SAFE — use these instead
element.textContent = userInput; // Escaped automatically
element.setAttribute('data-id', id); // Safe for attributes
document.createTextNode(userInput); // Creates safe text node
上述安全模式(textContent、通过 setAttribute 转义属性、DOMPurify.sanitize)是处理 DOM 中用户输入的唯一正确方式。
URL 验证
function isSafeURL(url) {
try {
const parsed = new URL(url);
return ['http:', 'https:'].includes(parsed.protocol);
} catch {
return false;
}
}
// Usage
const href = isSafeURL(userURL) ? userURL : '#';
特定上下文的编码
不同上下文需要采用不同的编码方式:
- HTML 实体编码:文本内容最安全的选择
- 属性编码:用于 HTML 属性
- JavaScript 转义:用于脚本上下文
- URL 编码:用于 URL 参数
- CSS 转义:用于样式表上下文
始终根据数据将要呈现的具体上下文对输出进行编码。
其他实现
请参阅 references/python-sanitization.md,了解:
- Python bleach 库的用法
- Flask/Django 模板转义
- 服务端验证模式
请参阅 references/nodejs-advanced.md,了解:
- 包含所有方法的完整 XSSPrevention 类
- Express 中间件(xssProtection)
- React 组件(SafeText、SafeHTML、SafeLink、useSanitizedInput)
- Helmet CSP 配置
最佳实践
✅ 应该:
- 默认对输出进行编码
- 使用具有自动转义功能的模板引擎
- 实施 CSP 标头
- 使用允许列表清理富文本内容
- 通过协议白名单验证 URL
- 使用 HTTPOnly Cookie
- 定期进行安全测试
- 利用安全框架
❌ 不应该:
- 信任用户输入
- 使用不安全函数(eval、innerHTML)
- 为了方便而禁用安全功能
- 仅依赖客户端验证
- 使用阻止列表而非允许列表
- 跳过特定上下文的编码
- 允许任意脚本执行
安全检查清单
- 根据上下文对所有输出进行编码(HTML、属性、JS)
- 使用允许列表(而非阻止列表)清理 HTML
- 实施严格的 CSP 标头
- 使用 HTTPOnly Cookie 保存会话
- 验证并清理 URL
- 避免使用 innerHTML 处理用户内容
- 定期进行安全测试
资源
评论
支持 Markdown