SuperAPI AI 工具集

push-preflight

安全与审计

查看项目

更新于 10-13 16:58

技能介绍

Push Preflight 是一个正式的推送前安全检查技能,在每次向非本地文件路径的远程仓库执行 git push 之前运行。遇到密钥命中即拒绝;对体积/禁止文件给出警告;推送前确认用户意图。

使用场景:当用户要求推送,或 Claude 在向任何远程执行 git push 之前,都可使用本技能。它与 git-ops 互补(后者负责推送本身),本技能是紧邻推送前运行的关卡。

名称由来:原名 push-gate。由于它运行六项检查(密钥扫描、工作树干净、禁止文件、快进、体积提示、开放 issue 提示),叫 secret-scan 会低估其功能并产生误导——它只扫描正在推送的提交,从不扫描历史(历史扫描属于 security-ops)。名称与 scripts/preflight.sh 一致。描述中把密钥扫描放在首位,因为真正用于选择技能的是描述而非名称。

硬性规则:

  • gitleaks 是必需依赖。若未安装,则输出安装说明并拒绝,不会静默回退到仅正则模式。
  • 任何密钥扫描命中即拒绝,无绕过标志。已确认安全的发现写入仓库内提交的允许清单(gitleaks 用 .gitleaksignore,正则层用 .push-preflight-allow),从不使用内联覆盖。真实密钥会迫使用户重写历史并重新调用该关卡。
  • 绝不使用 --force 推送。该关卡从不传递 force 标志。若用户需要强制推送,需另行沟通并明确授权。
  • 绝不使用 --no-verify。不跳过钩子。
  • 工作树必须干净。工作树脏则拒绝(未提交的工作可能被意外带入推送流程)。
  • 必须指定远程名。若 git push 未明确指定远程和分支,则拒绝。

工作流程: 第 1 步 → 识别远程 + 分支 第 2 步 → git fetch <remote> 第 3 步 → 验证工作树干净 第 4 步 → 计算待推送提交(数量 + 列表) 第 5 步 → 检查分叉(非快进 ⇒ 要求用户先 rebase) 第 6 步 → 密钥扫描(gitleaks 遵循 .gitleaksignore,正则层遵循 .push-preflight-allow) 第 7 步 → 禁止文件扫描(任何命中即拒绝) 第 8 步 → 体积提示;开放 issue 提示(github-ops;仅信息性,不设关卡) 第 9 步 → 明确确认 第 10 步 → git push <remote> <branch> 第 11 步 → 推送后校验(ls-remote 与推送的 SHA 匹配)

调用方式: 从仓库根目录(最常见): bash .claude/skills/push-preflight/scripts/preflight.sh <remote> <branch>

从其他技能以不同 cwd 调用时(例如 github-ops): bash $HOME/.claude/skills/push-preflight/scripts/preflight.sh --cwd <repo-root> <remote> <branch>

--cwd 必须位于位置参数之前。省略时,脚本针对 $PWD 运行。

脚本会打印结构化报告并以以下退出码退出:

  • 0:所有关卡通过,可推送;请用户确认,然后 git push <remote> <branch>
  • 1:密钥扫描器命中;向用户报告;拒绝;建议 git filter-repo / BFG
  • 2:添加了禁止文件(.env、密钥文件、.claude/settings.local.json、worktree 路径等);报告;拒绝
  • 3:工作树脏;报告;请用户先提交或 stash
  • 4:非快进分叉;报告;请用户先 rebase 或 merge
  • 5:缺少依赖(gitleaks);报告安装说明;拒绝
  • 6:未指定远程 / 未知远程;报告;请求澄清

依赖:

  • gitleaks(必需):用于带维护规则语料的密钥检测。安装:Windows 用 scoop install gitleaks 或 winget install gitleaks.gitleaks / macOS 用 brew install gitleaks / Linux 用 apt install gitleaks,或从 https://github.com/gitleaks/gitleaks/releases 获取二进制文件。
  • ripgrep(必需):正则回退层 + 禁止文件扫描。通常已预装;winget install BurntSushi.ripgrep.MSVC / brew install ripgrep。
  • git ≥ 2.30:核心操作。

两个密钥层都必须通过:gitleaks 使用维护的语料库检测已知令牌格式;正则层捕获 gitleaks 可能遗漏的通用 password = "..." / DSN / 连接字符串模式。正则语料见 references/secret-patterns.txt。gitleaks 使用 references/gitleaks-config.toml 运行(默认规则集 + 为设计上公开的令牌提供的允许清单,例如 Mapbox pk.*);若该文件不存在,扫描回退到 gitleaks 内置默认配置。

触发短语:

  • 直接:"push to origin"、"push to github"、"push to remote"、"git push"
  • 疑问:"can we push?"、"safe to push?"、"ready to push?"
  • 显式:/push-preflight、"run push-preflight"(原名 push-gate) Claude 应在以上任一情况调用 scripts/preflight.sh。不要在本地推送(git push <path> 或 git push .)时调用——那是用于跨 worktree 落地的 updateInstead 模式,不离开宿主机。

误报处理: 两个密钥层都有仓库内、已提交的允许清单。该关卡仍会拒绝任何未被明确允许的命中,且该技能不提供内联绕过——已确认安全的发现应在仓库中获得一条经审查的条目,而非一次性覆盖。

层级与允许清单文件(仓库根):

  • gitleaks:.gitleaksignore;条目格式为 gitleaks 指纹(commit:file:rule:line)
  • 正则:.push-preflight-allow;条目格式为 <repo-relative-path>:<line-regex>

正则层还会在查询允许清单之前自动丢弃常见误报(环境变量引用、shell 回退、带 ... 的占位符)。

旧名称 .pushgate-allow(来自 push-gate 时代)仍会被读取,并在 stderr 输出一行弃用提示。若两个文件都存在,其条目会合并:每条都是经审查、已提交的决定,因此半途的迁移不会开始拒绝以前能通过的推送。迁移方式:git mv .pushgate-allow .push-preflight-allow(或移动条目)并提交。

.push-preflight-allow 规则:

  • 每行一条;允许 # 注释。每条条目的正上方必须带有原因注释——缺少时扫描器会警告。
  • 条目在第一个 : 处分割——先是仓库相对路径(正斜杠,路径中不含 :),然后是匹配所添加行完整内容的 Rust 正则。任何地方都不使用行号:行号会在其上每次编辑时漂移;内容锚点不会。
  • 一条条目只在该精确文件中抑制命中。其他所有命中仍会拒绝。
  • 拒绝时,扫描器会为每个命中打印一条现成的带锚点条目——将其复制到原因注释下,提交,重新运行关卡。
  • 文件已不存在,或正则不再匹配该文件在分支顶端的任何行的条目,会被报告为过期(警告,不设关卡)——请清理它们。
  • 关卡的干净工作树规则(硬性规则 5)意味着在查询该文件时它总是已提交——未提交的允许清单编辑会在第 3 步失败,无法抑制任何内容。

示例:

reason: test fixture — wire-snapshot key exercised by MCP wire tests, not a credential

packages/mcp/test/client.test.ts:^ apiKey: "wire-snapshot-key",$

不在范围内:

  • 发布自动化(changelog、打标签、版本号提升)——属于 ci-cd-ops / git-ops 领域。
  • 完整安全审计——属于 security-ops(更广泛的 SAST + 依赖扫描)。
  • 强制推送 / 历史重写——有意排除;需要显式带外授权。
  • 签名提交验证——需要时再添加。

文件:

  • SKILL.md:本文件——工作流 + 规则
  • scripts/preflight.sh:主编排(第 1–8 步)
  • scripts/scan-secrets.sh:gitleaks + 正则层(第 6 步)
  • references/secret-patterns.txt:正则语料 + 误报过滤词
  • references/gitleaks-config.toml:gitleaks 配置:默认规则 + 公开令牌允许清单(存在时由 scan-secrets.sh 使用)
  • tests/run.sh:密钥扫描器的离线行为自测(植入的密钥、误报过滤、允许清单、过期条目、旧允许清单名)
  • assets/:(空;预留给未来的报告模板)

按仓库(不随技能发布):.gitleaksignore 和 .push-preflight-allow,提交在被扫描仓库的根目录——见"误报处理"一节。