didrod205/csp-doctor

GitHub: didrod205/csp-doctor

本地离线的 CSP 策略静态分析 CLI 工具,用于检测 Content-Security-Policy 中的 XSS 绕过风险并支持 CI 门控。

Stars: 1 | Forks: 0

# 🛡️ csp-doctor ### 在本地为你的 Content-Security-Policy 进行 XSS 漏洞 Lint —— 无需将内容粘贴到任何网站。 [![npm version](https://img.shields.io/npm/v/csp-doctor.svg?color=success)](https://www.npmjs.com/package/csp-doctor) [![bundle size](https://img.shields.io/bundlephobia/minzip/csp-doctor?label=core%20gzip)](https://bundlephobia.com/package/csp-doctor) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/4918a3bb9c010529.svg)](https://github.com/didrod205/csp-doctor/actions/workflows/ci.yml) [![types](https://img.shields.io/npm/types/csp-doctor.svg)](https://www.npmjs.com/package/csp-doctor) [![license](https://img.shields.io/npm/l/csp-doctor.svg)](./LICENSE) **[🌐 试试浏览器端演练场 →](https://didrod205.github.io/csp-doctor/)**  ·  粘贴一条 CSP,查看按严重程度排序的 XSS 漏洞。不会上传任何数据 —— 全部在客户端运行。
你添加了 `Content-Security-Policy` 来阻止 XSS。但是,`script-src` 中一个单一的 `'unsafe-inline'` 就会悄无声息地使整个策略失效;一个通配符或光秃秃的 `https:` 会让任何主机都可以提供脚本;而像 `ajax.googleapis.com` 这样的 CDN 白名单则会开启 JSONP/AngularJS 绕过漏洞 —— 因此攻击者*尽管*有你的策略,依然可以运行脚本。 唯一好用的分析器 Google CSP Evaluator 是**一个需要你粘贴内容的网站** —— 而不是你可以在 CI 中运行的东西。 **csp-doctor 可以在本地确定性地 lint 一个 CSP 的这些漏洞** —— 无论它是一个字符串、一个 HTML `` 标签,还是一个 headers 文件 —— 而且它**支持 nonce / hash / strict-dynamic**,因此它不会对现代浏览器已经忽略的 `'unsafe-inline'` 大惊小怪。 ``` npx csp-doctor scan -p "default-src 'self'; script-src 'self' 'unsafe-inline' ajax.googleapis.com" ``` ``` policy 57/100 (F) ✗ 'unsafe-inline' in script-src defeats XSS protection [script-src] ⚠ Allowlisted host enables a CSP bypass: ajax.googleapis.com [script-src] ⚠ No base-uri [base-uri] ⚠ No frame-ancestors [frame-ancestors] ``` ## 为什么选择 csp-doctor? - 🎯 **它了解各种绕过手法。** 内置的破坏白名单的主机列表(JSONP 端点、托管的 AngularJS)是 Google CSP Evaluator 背后的核心洞察 —— 现已内置以供离线使用。 - 🧠 **支持 nonce / hash / strict-dynamic。** 它明白 nonce 会使 `'unsafe-inline'` 成为一个无害的回退选项,并且 `'strict-dynamic'` 会忽略主机白名单 —— 因此它能正确评估*现代* CSP,而不是把所有东西都标记为有问题。 - 🔒 **本地且具有确定性。** 无需网站,无需 API 密钥,可离线运行并在 CI 中使用。相同的策略 → 相同的结果。拦截提交了 `'unsafe-inline'` 的 PR。 - 🧩 **从任何地方读取。** 可以是原始策略、HTML ``、`_headers` 文件、nginx `add_header`、Apache `Header set` 或 `vercel.json`。 为什么不把它粘贴到 LLM 中呢?可绕过主机的列表和指令回退规则(`script-src` → `default-src`,`base-uri` 不回退)是精确且不断演变的事实,聊天机器人通常会弄错这些 —— 而你需要的是对*每一次* CSP 变更进行门控,而不是仅此一次。 ## 安装 ``` # 立即运行 npx csp-doctor scan -p "" # 或者添加它 npm install -g csp-doctor # global CLI npm install -D csp-doctor # CI dependency ``` Node ≥ 18。核心代码零依赖且对浏览器安全(已为 Web 演练场做好准备)。 ## 快速开始 ``` csp-doctor scan -p "default-src 'self'; script-src 'self' 'nonce-abc'" # a string csp-doctor scan index.html # from csp-doctor scan _headers vercel.json # from configs curl -sI https://example.com | csp-doctor scan # from live headers csp-doctor scan -p "" --min-score 80 # CI gate csp-doctor init # write a config ``` 请参阅 [`examples/sample-report.md`](./examples/sample-report.md),以及 [`examples/strong.csp.txt`](./examples/strong.csp.txt) 获取获得 100 分的策略。 ## 检查内容 | 分组 | 示例 | | ----- | -------- | | **XSS 暴露** | `'unsafe-inline'`(错误 —— 或在 nonce/hash 使其失效时仅为提示信息)、`'unsafe-eval'`、通配符 `*`、光秃秃的 `https:`/`http:`、`script-src` 中的 `data:` | | **白名单绕过** | 已知会破坏 CSP 白名单的主机(JSONP / 托管的 AngularJS),除非 `'strict-dynamic'` 抵消了该白名单的限制 | | **缺失的指令** | 缺少 `object-src 'none'`、缺少 `base-uri`、缺少 `frame-ancestors`、缺少 `default-src` 回退 | | **强化与元数据** | 没有 nonce 的 `'strict-dynamic'`、已弃用的 `report-uri`,以及 Report-Only 策略(它们**什么都不拦截**) | 每个发现都是一个加权过的 错误 / 警告 / 提示;策略最终会汇总为一个 0–100 的分数和 A–F 的等级,你可以将其用于 CI 门控。 ## 实际场景 **1. 在 CI 中对你的 CSP 进行门控。** 如果一个 PR 在你的策略中添加了 `'unsafe-inline'` 或可绕过的 CDN,将会导致构建失败: ``` # .github/workflows/ci.yml - run: npx csp-doctor scan next.config.js --min-score 85 # or your _headers / meta ``` **2. 在发布前审计策略。** 粘贴你即将部署的标头并查看漏洞 —— 在本地完成,无需将你的配置发送给第三方网站。 **3. 对安全发现进行分类排查。** 扫描器提示“CSP 脆弱” —— `csp-doctor scan` 会告诉你*是哪个*指令以及*为什么*,并提供确切的修复方法。 ## 配置 `csp-doctor init` 会写入 `csp-doctor.config.json`: ``` { "ignore": [], // rule ids to skip, e.g. ["missing-default-src"] "bypassHosts": [], // extra hosts to treat as bypass-prone "allowHosts": [], // hosts you've audited and accept (suppress the finding) "minScore": 0 // CI gate threshold } ``` ## 库 API ``` import { analyzeCsp, DEFAULT_CONFIG } from "csp-doctor"; const [report] = analyzeCsp("inline", "script-src 'self' 'unsafe-inline'", DEFAULT_CONFIG); for (const f of report.findings) console.log(f.severity, f.rule, f.directive); ``` 同时导出的还有:`analyzePolicy`、`parsePolicies`、`extractPolicies`、`findBypass`、`BYPASS_HOSTS` 以及各种类型。核心代码具有零运行时依赖。 ## 路线图 - 🤖 **可选的 `--ai` 层(自带 API 密钥)**,用于为你的应用起草强化后的替换策略。核心功能保持 100% 离线和确定性。 - `require-trusted-types-for` / Trusted Types 评分。 - 针对 `style-src` 和 `connect-src` 的特定检查(CSS 数据泄露、信标主机)。 - 自动建议迁移到 nonce + `'strict-dynamic'` 策略。 - ✅ **一个浏览器演练场** —— 粘贴策略,查看审计结果,不上传任何内容。 [在这里体验](https://didrod205.github.io/csp-doctor/)。 ## 许可证 [MIT](./LICENSE) © csp-doctor 贡献者
标签:CSP, GNU通用公共许可证, MITM代理, Node.js, Web安全, XSS, 代码检查工具, 安全标准, 文档结构分析, 暗色界面, 漏洞情报, 自动化攻击, 蓝队分析