让 Git 钩子可见

💡 原文英文,约700词,阅读约需3分钟。
📝

内容提要

作者受 Git 钩子攻击事件启发,利用 zsh 的 chpwd 函数在进入仓库时提示已启用的钩子,并检查 .pre-commit-config.yaml 是否已安装 pre-commit 钩子,以防遗忘。

🔎

延伸解读

攻击场景与钩子可见性

文章提到,Frank Wiles 差点中招的攻击并非来自克隆的仓库,而是通过 Dropbox 共享的本地检出,其中钩子已被启用。这提醒我们,钩子可能在不经意间被激活。作者因此希望让钩子更可见,以便及时发现异常。

zsh 的 chpwd 函数实现

作者利用 zsh 的 chpwd 函数,在切换目录时自动检查并列出当前仓库中已启用的钩子。脚本通过 git rev-parse 获取钩子目录,并筛选出可执行且非 .sample 的文件。为避免重复提示,每个仓库只提示一次。

pre-commit 配置检查

针对常见的 .pre-commit-config.yaml 文件,作者添加了第二个 chpwd 函数,用于检测 pre-commit 钩子是否已安装。如果未安装,会提示运行 pre-commit install 或 prek install。这有助于防止因忘记安装钩子而导致检查未运行。

实际效果与局限

作者发现这些函数能有效提醒钩子状态,并至少在一个项目中发现自己忘了安装 pre-commit。不过,他也指出提示可能过于频繁,久而久之可能被忽略。尽管如此,他认为这比完全不知情要好。

❓

Q&A

为什么作者想要让 Git 钩子变得可见?

作者受到 Frank Wiles 差点遭遇的 Git 钩子攻击事件的启发。该攻击中,一个通过 Dropbox 分享的本地检出仓库带有活跃的钩子,可能危及系统。因此作者希望在自己的机器上让 Git 钩子更加可见。

Git 钩子是什么?克隆仓库时会自动安装吗?

Git 钩子是位于仓库 .git 目录中的脚本,在各类 Git 操作期间运行。克隆仓库时不会在本地安装钩子,新克隆的仓库永远没有活跃钩子,必须由你在克隆后手动启用。

Frank Wiles 遭遇的攻击为什么危险?

因为攻击载体不是克隆的仓库,而是一个本地检出仓库,其钩子已被安装,然后作为 Dropbox 文件夹分享。当它到达 Frank 的机器时,钩子已经处于活跃状态,而他并未察觉。

如何用 zsh 在进入 Git 仓库时自动显示活跃的钩子?

定义一个 chpwd 函数 git_show_hooks,通过 git rev-parse 获取钩子目录,遍历其中可执行且非 .sample 的文件,若有活跃钩子则用红色文字输出。然后用 add-zsh-hook chpwd git_show_hooks 注册。该函数只在首次进入仓库时提示,避免重复。

如何检查仓库中是否已安装 pre-commit 钩子?

定义另一个 chpwd 函数 git_check_precommit,检查仓库顶层是否存在 .pre-commit-config.yaml,然后查看钩子目录中的 pre-commit 文件是否由 pre-commit 或 prek 生成。若未安装,则提示运行 'pre-commit install' 或 'prek install'。同样用 add-zsh-hook 注册。

为什么需要在 shell 启动时手动运行这些函数?

因为 zsh 在启动新 shell 时不会自动运行 chpwd 函数,所以需要显式调用 git_show_hooks 和 git_check_precommit 来检查初始目录。

🏷️

标签

➡️

继续阅读