一个能让你的编码代理在打开文件夹的瞬间就运行代码的仓库。GuardSkill 会在你操作之前对其进行检查。
npx guardskill .
只读。无网络调用、无遥测、无配置、无账户。它读取 git 配置和钩子脚本,打印发现的内容,然后退出。
编码代理在打开项目后会立即通过运行普通的 git 命令(如 git status、git diff)来收集上下文。Git 会从仓库自身的 .git/config 中读取设置,其中一些设置会指定一个供 git 执行的程序。如果在 core.fsmonitor 中放入一条命令,它就会以你的权限、在任何沙箱之外、在你输入任何内容之前运行。
两项公开研究使这一问题变得具体:
.git/config 不会通过克隆传输。仓库必须以文件形式连同其 .git 目录一起到达——例如压缩包、共享驱动器、同步文件夹、U 盘,或一个解压归档文件的代理。(Manifold Security、The Hacker News)@github/copilot 1.0.43 中通过强制设置 safe.bareRepository=explicit 修复。(GitHub Advisory)两份报告推荐的用户侧缓解措施是相同的:在使用代理打开目录之前检查 git 配置。 手动在整棵树中执行这一操作非常繁琐。此工具可在一秒内完成。
GuardSkill 遍历整棵树并查找代理可能获取的每个 git 配置:项目自身的 .git、任何作为内容到达的嵌套 .git、隐藏在子目录中的任何裸仓库、子模块或链接工作树留下的 .git 文件,以及 git 在主配置旁保留的配置——config.worktree 和每个 .git/modules/<name>/config。每一项都会被检查。
npx guardskill . # 扫描当前项目
npx guardskill ~/code/some-project # 扫描指定路径
npx guardskill . --json # 机器可读输出
npx guardskill . --out report.md # 同时写入 Markdown 报告
npx guardskill . --fail-on critical # 仅在发现严重问题时使构建失败
npx guardskill . --exclude test/fixtures # 跳过某个目录
退出代码:0 表示没有达到或超过阈值的发现,1 表示存在达到或超过阈值的发现(默认阈值:high),2 表示扫描本身失败。
在 CI 中:
- name: Check for git execution vectors
run: npx guardskill . --fail-on high
示例输出:
GuardSkill - git execution-vector scan (read-only)
Path: /Users/dev/projects/inherited-project
Git configurations inspected: 2 Directories walked: 148
[CRITICAL] vendor/payload.git - Bare git repository found inside the project tree
what Git discovers bare repositories while walking directories and applies their
configuration, including keys that execute commands.
found bare repository at vendor/payload.git
do Do not open this project with a coding agent until you have inspected the directory.
[CRITICAL] vendor/payload.git/config:3 - core.fsmonitor runs an external command
found core.fsmonitor = /tmp/.x/run.sh
2 critical, 0 high, 0 medium, 0 low.
Nothing was changed - this scan only reads.
一个会喊“狼来了”的安全工具会被卸载。该测试套件针对 29 个真实的干净仓库 运行——包括 git-lfs、git-crypt、husky、.githooks 约定、已注册的子模块、凭据助手、自定义编辑器和分页器、签名配置——如果其中任何一个产生高于信息级别的发现,构建就会失败。它还针对 22 个围绕已知攻击模式构建的仓库 运行,如果任何一个被遗漏或被错误的规则捕获,构建同样会失败。
在此之上还有一个规避测试套件:其中的每个案例都是通过攻击一个已通过自身测试的 GuardSkill 版本而发现的,并且它会在每次提交时运行,以确保未来的更改不会悄悄重新打开某个漏洞。它覆盖了 git 仍接受的各种拼写方式(大小写、引号、行续接、CRLF、字节顺序标记、节行上的键)、以常见工具命名的载荷、名为 .husky 以显得常规的钩子目录,以及隐藏在第一个版本从未查看过的位置的配置。一个健壮性测试套件会向其输入二进制、空、截断和 200,000 行的配置文件、不可读目录、符号链接循环以及指向树外的指针,并要求输出报告而非堆栈跟踪。
两个深思熟虑的设计选择:
.githooks 目录会被报告为信息级别(low)而非风险——但 GuardSkill 仍会读取脚本,如果其中某个脚本在运行前获取或解码代码,则会升级为 critical。include / includeIf 始终会被报告。 include 可以在之后引入此列表中的任何键,这正是隐藏键的方式。你自己编写的共享 ~/.gitconfig 是一个可以忽略的正常发现。npm test 的 .husky 属于信息级别,且发现会列出将要运行的内容。同一个目录运行 /tmp 中的内容则不然。它永远不会修改任何内容。它不会执行它发现的任何内容。它不进行任何网络调用,也不收集任何遥测数据——离线运行它,行为完全相同。它目前还不会扫描 npm 依赖、.claude/settings.json、.vscode/tasks.json 或 MCP 服务器定义;这些是下一类问题,而非本工具的范围。而且它是一个信号,而非判决:阅读发现、查看证据、自行判断。
本仓库中的 SKILL.md 允许编码代理在打开不熟悉的项目之前自行运行扫描。将目录复制到你的技能文件夹中,或将你的代理指向该仓库。
npm test # 重新生成测试夹具,然后运行测试套件
测试夹具由代码生成(test/fixtures/generate.js),而非手动提交,因此扩展干净或易受攻击的集合只需几行代码。新的检测规则放在 rules/git-exec-keys.json 中——没有两侧夹具的规则将不会被合并。
持续监控、Slack/Teams 警报和自动修复拉取请求计划作为付费层提供。扫描器本身保持免费且采用 MIT 许可证。检测规则保留在开放仓库中——一个你无法阅读其规则的安全工具不值得信任。
MIT。由 Helios IT Solutions(一家荷兰 IT 服务提供商)构建和维护。安全问题:请参阅 SECURITY.md。
| 类别 | 检查项 |
|---|
| 直接执行键 | core.fsmonitor、core.sshCommand、core.gitProxy、core.pager、core.editor、sequence.editor、diff.external、uploadpack.packObjectsHook |
| 间接执行键 | filter.*.clean / .smudge / .process、diff.*.textconv、merge.*.driver、mergetool.*.cmd、difftool.*.cmd、credential.helper |
| Shell 别名 | 任何值以 ! 开头的 alias.* |
| 从其他位置加载的配置 | include.path、includeIf.*.path |
| 钩子 | core.hooksPath 覆盖项、.git/hooks 中活动的(非 .sample)脚本,以及将下载内容通过管道送入 shell 或在运行前解码 base64 的钩子脚本 |
| 传输协议 | protocol.allow 和 protocol.<name>.allow 被重置为 always,以及任何使用 ext:: 传输协议的远程或子模块 URL,该协议会将行的其余部分交给 shell 处理 |
| 结构 | 树内的裸仓库(CVE-2026-45033 向量)、未注册为子模块的嵌套 .git 目录、指向树内 git 目录的 .git 文件 |