Nginx防XSS核心是配置安全响应头而非过滤内容,必须设Content-Security-Policy并加always,禁用X-XSS-Protection(现代浏览器已弃用),所有安全头如X-Content-Type-Options、X-Frame-Options均需加always确保错误响应也受保护。

Linux 上配置 Nginx 的 XSS 防御,核心不是“过滤脚本”,而是通过响应头阻断攻击链——Content-Security-Policy 必须配,X-XSS-Protection 可关,所有安全头都要加 always。
为什么不能靠 Nginx 过滤 HTML 或 JS?
Nginx 不解析响应体内容,也不执行 JS,所以无法像 WAF 那样清洗 <script> 标签或转义用户输入。它只负责发响应头、转发请求、限流。指望 if ($args ~* script) 拦 XSS 是无效的:攻击载荷可以 Base64 编码、用事件属性(onerror=...)、或藏在 JSON 里绕过简单正则。
- 真正防 XSS 的主战场在应用层:输出编码、输入校验、CSP 策略
- Nginx 的角色是加固终端防护层,补上浏览器行为控制缺口
- 任何试图用
rewrite或if拦截 XSS 载荷的配置,都会漏报且易被绕过
必须加 always 的安全响应头怎么写?
错误配置:add_header X-Content-Type-Options nosniff; —— 404、500 响应不带这个头,攻击者可构造错误路径触发 MIME 嗅探执行脚本。
正确写法(全部加 always):
add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; object-src 'none'; base-uri 'self';" always;
-
always确保所有状态码(包括 404、500、302)都携带该头 -
Content-Security-Policy中禁用'unsafe-inline'和'unsafe-eval',否则内联脚本和eval()仍可执行 - 若用
script-src白名单,必须列出所有合法 CDN 域名,不能写*
要不要配 X-XSS-Protection?
现代浏览器(Chrome 78+、Firefox 95+、Edge 100+)已完全弃用该头。它仅对旧 IE/旧 Safari 有效,且 mode=block 在部分场景下会误杀合法动态内容(如富文本编辑器渲染)。
- 如果后端已部署严格 CSP + 输出编码,直接删掉
add_header X-XSS-Protection ...更干净 - 若需兼容极老客户端,设为
"0"(显式关闭),而不是留空——留空时浏览器按默认"1"行为,反而可能引入不可控拦截 - 绝不要设成
"1"(无mode=block):此时浏览器尝试“修复”而非阻断,极易被绕过
多租户环境下 CSP 怎么隔离?
单个全局 Content-Security-Policy 头无法适配不同租户的资源域名。例如租户 A 用 https://a-cdn.example.com,租户 B 用 https://b-cdn.example.com,硬编码会互相冲突。
可行做法是用 map 动态生成头:
map $host $csp_tenant {
~^a\.example\.com$ "default-src 'self'; script-src 'self' https://a-cdn.example.com;";
~^b\.example\.com$ "default-src 'self'; script-src 'self' https://b-cdn.example.com;";
default "default-src 'self';";
}
add_header Content-Security-Policy $csp_tenant always;- 避免在
server块里用if判断域名再 set 变量——Nginx 的if在 header 设置上下文中不可靠 -
map必须定义在http{}块顶层,不能嵌套 - 租户域名匹配失败时 fallback 到最小策略,防止空值导致 CSP 失效
CSP 策略上线前务必用 Content-Security-Policy-Report-Only 收集违规日志;always 是所有安全头的底线要求,漏掉就等于在错误响应里主动打开后门。


















