Community研究与数据分析github.com

vitwit/deploy-security-gate

部署安全检查门,用于产品规模化发布和运行。能够发现暴露的API密钥和机密信息(源码、Git历史、前端/移动端构建产物、Dockerfile、CI工作流、编码代理配置),审查AI网关/LLM、支付和分析集成,标记单点故障,并基于固定检查清单生成“通过/不通过”报告。

deploy-security-gate 是什么?

该技能是一个全面的部署安全检查门,旨在防止因密钥泄露或单点故障而导致的生产事故。它通过三个步骤执行:自动扫描(使用 `scripts/scan.py` 快速检测已知机密模式)、代码审查(比照 `references/integrations.md` 检查每个已发现的集成,如AI网关、支付服务和分析工具)以及手动检查(针对无法从仓库验证的项目,如仪表板限额、轮换策略和备份恢复演练)。 该技能支持Claude Code、Cursor等编码代理,并可集成到CI/CD流水线中。其核心优势在于:它不仅自动化了约三分之一的检查清单,还明确指出了哪些项目需要人工确认,从而生成一个诚实、可操作的“通过/带例外通过/不通过”报告。对于用户而言,这是发布前最后一道防线,能够捕捉测试、构建和部署中容易被忽略的安全配置错误,如未验证的Webhook、客户端暴露的密钥或单点AI供应商风险。

兼容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/vitwit/claude-plugins/tree/HEAD/deploy-security-gate/skills/deploy-security-gate

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

部署安全检查门

此技能执行一个检查清单:绝无密钥暴露,且无单点故障导致产品瘫痪。它通过三个步骤执行:

  1. 使用 scripts/scan.py 进行自动扫描,快速、确定且只读。
  2. 参照 references/integrations.md 对每个检测到的集成进行代码审查。
  3. 对无法从仓库确认的项进行手动检查,例如供应商仪表板、密钥轮换、备份和演练。这些项来自 references/checklist.md。

仅凭扫描不算通过。它只覆盖了大约三分之一的检查清单。此技能的价值在于完整执行所有三个步骤,并诚实地报告哪些已验证、哪些仍需要人工确认。

工作流程

1. 范围界定

明确需要发布的内容:

  • 仓库根目录
  • 前端或移动端构建产物(如果有)
  • 部署目标,例如容器、Serverless 或 Kubernetes
  • 是首次发布、新集成还是日常维护

如果用户指定了具体变更,例如“添加 Stripe”,则将审查重点放在其上。但仍需运行完整扫描,因为其他地方的漏洞同样会阻止发布。

2. 运行扫描器

python3 <skill-dir>/scripts/scan.py <repo> --history
  • 为每个构建产物目录(dist、.next/static、解压后的 APK/IPA)添加 --build-dir <dir>。已发布的构建产物中,“公共”密钥有时可能是机密密钥。常见构建目录会自动检测;如果不存在,请先构建应用。
  • --entropy 会添加高熵检查,以捕获已知模式无法识别的自定义机密(低严重性;报告前需逐一验证)。
  • --format json 或 --format sarif 提供机器可读输出;SARIF 可上传至 GitHub 代码扫描。--fail-on high|medium|low|never 控制退出码,在 CI 中很有用。
  • 确认的误报可以通过行内注释 # security-gate: allow 或仓库根目录下的 .security-gate-ignore 文件(参见 README)进行抑制。优先抑制特定发现,而非降低 --fail-on 级别。
  • 扫描器会屏蔽机密值。你在所有输出中都必须保持这一点:切勿将完整密钥写入聊天会话、文件、提交或 PR 文本,因为这会引发二次泄露。

扫描器检查:

  • 工作目录、构建产物和 Git 历史中的机密模式(AWS、Anthropic、OpenAI、OpenRouter、Groq、xAI、Perplexity、Replicate、fal、Google API 密钥和 OAuth 机密、Stripe 生产密钥和 Webhook 机密、Razorpay、GitHub、GitLab、Slack Tokens 和应用 Token、GCP 服务账号、npm、PyPI、SendGrid、Hugging Face、DigitalOcean、New Relic、Shopify、Square、Databricks、Doppler、PlanetScale、Linear、Azure Storage 密钥、Mailgun、Telegram、Discord Webhook、JWT、私钥、带密码的数据库 URL、硬编码的 *_SECRET / *_TOKEN / *_SERVICE_ROLE 赋值(带引号(包括 JSON/MCP 配置)或不带引号))
  • 使用 --entropy 检查不符合已知格式的高熵字符串(自定义或新颖的机密)
  • 已提交的 .env 文件和缺失的 .gitignore 条目
  • 客户端暴露前缀(NEXT_PUBLIC_、VITE_、REACT_APP_、EXPO_PUBLIC_ 等)后面的机密类变量,以及客户端代码中的直接 LLM 调用
  • 构建产物中的 Source Map
  • GitHub Actions 工作流:标签固定的 Actions、pull_request_target、缺失 permissions: 块、回显的机密、写入文件或 $GITHUB_ENV / $GITHUB_OUTPUT 的机密、静态云密钥而非 OIDC、以及运行生命周期脚本的安装指令
  • Dockerfile:ARG/ENV 中的机密、复制的 .env 文件、以 root 用户运行
  • 无签名验证的支付 Webhook 处理器
  • 编码代理对 .env 文件的读取权限
  • 正在使用的集成,以及 AI 和支付领域的单一供应商(单点故障)提示

3. 对发现结果进行分类

扫描器通过模式匹配工作,因此在报告每个发现前,务必通过阅读代码进行确认。

  • 发现生产密钥(在代码树、Git 历史或构建产物中):即使仓库是私有的,也视为已泄露。遵循 references/leaked-key-runbook.md,首先撤销密钥,清理工作稍后进行。撤销或轮换密钥会改变生产环境,因此须告知用户具体的密钥、发现位置以及撤销步骤。让用户执行,或在你自己执行前获得确认。
  • 误报(测试夹具、已记录的公共密钥):说明为何安全,然后继续。
  • 启发式发现(Webhook 验证、客户端 LLM 调用):打开文件检查实际的控制流。验证逻辑可能位于其他地方的中间件中。

4. 审查每个已发现的集成

对于扫描器列出或在代码中找到的每个集成,阅读 references/integrations.md 中的相应内容,并对照代码进行检查。这一步能捕获模式无法发现的问题,例如:

  • 作为开放代理的后端代理
  • 从请求体中获取的模型名称
  • 在客户端计算的金额
  • 使用管理员凭据运行的“工具”调用
  • 发送到分析工具的 PII
  • 无租户过滤器的 RAG 查询
  • 间接提示注入:模型读取的文档、网页、转录文本或工具结果被当作指令处理(检查清单 3.17)
  • 文件上传未经类型/大小/归档检查且未使用沙箱处理(3.18)
  • SSRF:模型或工具获取的 *_url 未阻止私有地址或元数据地址(3.19)

Webhook、客户端 LLM 和机密的检查是启发式的:扫描器能标记候选者,但可能遗漏手动编写的控制逻辑或非标准布局。务必通过阅读代码确认——使用 createHmac + timingSafeEqual 验证的 Webhook,或恰好位于 src/ 下的后端,即使工具标记或遗漏了它们,通常也是安全的。

5. 检查单点故障

使用检查清单第 10 部分,在代码和 IaC 中查找:

  • 一个 LLM 供应商,无回退
  • 与供应商的 HTTP 客户端,无超时或重试
  • 请求路径上的供应商调用,在分析宕机时阻塞
  • 单区域或单可用区的数据库
  • 无缓存的密钥获取
  • 根据用户所述,唯一持有根或所有者权限的人员

6. 手动检查

许多检查清单项无法从仓库验证,例如:

  • 供应商仪表板上的消费上限
  • 轮换计划
  • 供应商账号上的 SSO 和 MFA
  • 备份恢复测试
  • 故障转移演练
  • 数据处理协议 (DPA)
  • 支付页面上的 PCI 脚本清单

将这些项列为 Needs confirmation(需要确认),每项附带一个针对负责人的问题。切勿仅凭假设就标记为通过。一个默默通过未验证项的检查门比没有更糟糕。

7. 报告

使用以下结构,以使结果在发布期间具有可比性:

# 安全检查门:<产品 / 变更> — <GO | NO-GO | GO WITH EXCEPTIONS(通过 | 不通过 | 带例外通过)>

## 阻塞项(部署前必须修复)
- [检查项ID] 文件:行号 — 问题 — 修复方法

## 应修复项(本迭代)
- ...

## 已审查的集成
| 集成 | 仅服务端 | 限定密钥 + 消费上限 | Webhook/输出已验证 | 回退 | 备注 |

## 需要确认(手动)
- [ ] <给负责人的问题>(检查清单 §n)

## 已通过(已验证)
- <项> — 验证方式

裁决规则:

  • NO-GO(不通过): 任何确认的 HIGH 严重性发现,包括生产环境密钥泄露、客户端暴露的密钥、未验证的支付 Webhook 或 CI 日志中的密钥。
  • GO WITH EXCEPTIONS(带例外通过): 仅剩 MEDIUM 或 LOW 级别发现,且用户接受这些发现,并指定了负责人和截止日期。
  • GO(通过): 无未关闭项,且所有手动项均已确认。

修复问题

当用户要求你修复发现时,建议采用这些从根源而非表面解决问题的补救措施:

  • 代码中的密钥: 替换为运行时查找,从机密管理器注入的环境变量或通过供应商的 SDK 获取。向 .env.example 添加占位符。切勿在任何地方写入真实值。告知用户密钥仍需要撤销,因为从代码中移除并不能解除泄露。
  • 密钥到达客户端: 将调用移至后端路由或 AI 网关,该网关对用户进行身份验证、按用户和租户限流、允许特定模型和操作,并持有密钥。客户端仅保留可发布的密钥。
  • 未验证的 Webhook: 使用供应商 SDK 验证原始主体上的签名。拒绝过时的时间戳,按事件 ID 去重,并在状态变更前从供应商处重新获取对象。
  • CI 问题: 将 Actions 固定到提交 SHA(使用 git ls-remote 解析 SHA,在注释中保留标签)。添加 permissions: contents: read。用 OIDC 替换静态云密钥。使用 npm ci --ignore-scripts。
  • Docker 问题: 对于构建时机密,使用 BuildKit RUN --mount=type=secret,并使用非 root USER。
  • 代理访问: 向 .claude/settings.json 添加 permissions.deny 条目 Read(./.env) 和 Read(./.env.*)。建议运行时注入(doppler run、infisical run、op run),以使纯文本文件不存在。

持续使用

建议将扫描器集成到 CI 中,以便在每次 PR(而不仅仅是发布时)运行检查门:

- run: python3 tools/deploy-security-gate/scripts/scan.py . --fail-on high

同时建议按检查清单第 12 部分的节奏进行定期审查。

参考文件

  • references/checklist.md:完整检查清单(第 1–14 部分),每个项都标记有 [auto](扫描器)、[code](代码审查)或 [manual](负责人确认)。在第 5–6 步以及需要确切控制逻辑时阅读。
  • references/integrations.md:AI 网关和 LLM 供应商、MCP 服务器、支付、分析工具和身份认证的理想状态,以及需要查找的模式。阅读与审查范围相关的部分。
  • references/leaked-key-runbook.md:发现生产环境密钥时的分步响应指南,包括针对每个供应商的撤销步骤。

相关技能