关于 git-safety
git-safety 是用于检查暂存内容并管控破坏性 Git 操作的技能,也指导设置预防措施,以及在凭据轮换后经确认清理历史记录。
主要功能
- 01扫描暂存文件及新增行中的秘密
- 02评估破坏性 Git 操作与备份
- 03设置忽略规则和提交前钩子
- 04轮换凭据后指导经确认的历史清理
适用场景
- 01提交前检查暂存内容
- 02重置或删除引用前评估风险
- 03防止敏感文件进入后续提交
- 04从 Git 历史中移除已轮换的凭据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ shipshitdev/ skills --skill git-safety安装后在 Claude Code 中输入/git-safety确认已加载。
附带文件references/full-guide.md
详细介绍
Git 安全
两道防护,守护你每天都在使用的同一个代码库:
- 暂存防护 — 不让敏感信息进入下一次提交。
- 操作防护 — 未经确认且未做好备份,不运行破坏性 Git 命令。
两者都会持续运行:每次提交和推送时、每个分支上,始终如此。若要在整个代码库公开前进行一次性审计,那是另一种情况 — 请参阅相关内容。
授权范围
仅在用户请求和现有授权范围内操作;加载此技能不会赋予任何新权限。仅报告的请求必须保持为仅报告,遵守调用方对目标、主机、提供商和成本的限制,扩大范围前先征求同意,并将这些限制转告受委派者。
约定
输入:
- 代码库根目录
- 模式:
scan、guard、prevent、clean或full - 对于
clean:泄露的路径或密钥字符串,以及涉及的引用
输出:
- 暂存内容的检查结果,逐文件给出阻止/允许判定
- 破坏性操作的风险评估和备份命令
- 对任何已推送内容的轮换清单
创建/修改:
scan和guard:不更改文件prevent:.gitignore、.env.example和钩子文件clean:重写 Git 历史,且仅在明确确认后执行
外部副作用:
clean模式可能会强制推送重写后的历史- 需要在代码库之外的系统上轮换凭据
需要确认:
- 重写历史之前
- 强制推送或任何会丢弃远程提交的推送之前
- 执行
reset --hard、clean -fdx或删除分支/标签之前 - 更改共享代码库中的钩子或忽略规则之前
委派给:
- 无。建议在私有代码库公开前进行完整历史发布审计;对于超出 Git 状态范围的漏洞,建议进行应用安全审查。
默认将委派的安全检查设为 scan 或 guard。安装钩子、轮换凭据和重写历史都需要单独的授权操作;发现密钥不会自动授权执行这些更改。
先轮换
从 Git 历史中删除密钥并不意味着它就安全了。推送后:
- 机器人会在数秒内抓取新的推送
- 归档和镜像服务可能会保留快照
- 分叉会保留原始历史
- CI/CD 日志可能会保留该值
在处理历史之前,先在凭据来源处轮换凭据。重写历史是清理措施,不能用于遏制泄露。判定标准:签发该凭据的系统会拒绝旧值。
模式
| 模式 | 时机 | 结束条件 |
|---|---|---|
scan | 提交之前 | 每个暂存文件和新增行都已清除或标记 |
guard | 执行破坏性命令之前 | 已说明影响范围、完成备份并获得操作者确认 |
prevent | 每个代码库执行一次,之后在出现偏差时执行 | 忽略规则和钩子能阻止已知不安全的测试提交 |
clean | 确认泄露且完成轮换后 | 所有引用中都不再包含密钥,且已通知协作者 |
full | 新代码库接入时 | 已完成 scan → prevent |
scan — 暂存防护
检查范围是工作树和暂存差异,不包括历史。
# Files about to be committed
git diff --cached --name-only
# Sensitive filenames among them
git diff --cached --name-only | grep -iE '(^|/)\.env($|\.)|\.(pem|key|p12|pfx|secret)$|credentials|service-account|id_rsa|id_ed25519|\.npmrc$|kubeconfig'
# Secret-shaped values in added lines only
git diff --cached -U0 | grep -E '^\+' | grep -iE '(api[_-]?key|secret[_-]?key|client[_-]?secret|access[_-]?token|auth[_-]?token|password)[^a-z]{0,4}[=:][^=:]{8,}'
# Untracked files sitting in the tree that must never be added
git status --porcelain --untracked-files=all | grep -E '^\?\?' | grep -iE '\.env|\.pem$|\.key$|credentials|secrets\.'
对每项发现作出判定:阻止(真实凭据)、允许(占位符、测试样例或示例),或在仅凭差异无法判断该值类别时询问。对每项阻止结果报告文件和行号。所有暂存路径都有判定后即告完成。
guard — 破坏性操作关卡
以下任何操作都会改写或丢弃 Git 无法为协作者恢复的工作:
| 命令 | 丢弃的内容 |
|---|---|
git push --force / --force-with-lease | 其他人可能持有的远程提交 |
git filter-repo, bfg | 仓库中的所有提交哈希 |
git reset --hard | 工作树和暂存区中的未提交工作 |
git clean -fdx | 未跟踪文件,包括本地 .env |
git checkout -- <path> | 对该路径的未提交修改 |
git branch -D, git push origin --delete | 该引用上的未合并提交 |
git rebase on a pushed branch | 协作者手中的已发布提交 |
运行其中一项之前:
- 说明影响范围——哪些引用会发生变化、哪些人的克隆会失效、哪些内容无法恢复。
- 备份——改写历史时运行
git clone --mirror . ../repo-backup-$(date +%Y%m%d);运行reset --hard或clean -fdx前运行git stash -u。 - 优先选择可撤销的形式——使用
--force-with-lease而非--force;对已推送的分支使用git revert而非reset --hard;使用git stash而非checkout --。 - 向操作人员确认,并引用确切的命令。
操作人员针对已说明的影响范围确认后,或改用可撤销的替代方案后,即可结束。
prevent — 自动执行关卡
添加忽略规则、编写 pre-commit 钩子,并创建 .env.example。
模式、完整的钩子脚本和 git secrets 设置见
references/full-guide.md。
故意提交一个虚构的 .env 测试提交,并被钩子拒绝后,即可结束。
clean — 泄漏后改写历史
只有在确认凭据已轮换后,且仅能在上述 guard 关卡内运行。
git clone --mirror . ../repo-backup-$(date +%Y%m%d)
git filter-repo --path .env --invert-paths
git push origin --force --all && git push origin --force --tags
验证:
git log --all --full-history -- .env # empty
git log -p --all -S '<rotated-value>' # empty
两项验证均返回空结果,且每位协作者都已重新克隆后,即可结束。
紧急响应
凭据已出现在推送的提交中:
- 轮换凭据。在此之前,其他操作都不算完成。
- 检查服务提供商的访问日志,确认旧值是否被使用。
- 运行
clean,将其从历史记录中清除。 - 通过
guard关卡强制推送。 - 告知协作者重新克隆;分叉和未关闭的 PR 仍保留旧历史记录。
- 运行
prevent,避免再次暂存同一个文件。 - 记录泄漏了什么、何时泄漏,以及轮换了什么。
相关内容
- 发布前审计——发布私有仓库前的一次性检查:许可证和署名、整个历史记录中的机密信息、内部主机名和员工信息。在决定发布时运行一次;此后每次提交都运行
git-safety。 - 应用安全审查涵盖漏洞,而非 Git 状态。
完整的敏感文件模式、完整的 pre-commit 钩子脚本、.gitignore
模板、git secrets 设置、BFG 替代方案和平台说明:
references/full-guide.md