git 的 --end-of-options 参数为何被忽视
git's –end-of-options Flag

上周在排查一个包管理器的 CVE 漏洞时,我意外发现了 git 中一个鲜为人知的参数:--end-of-options。这个在 2019 年引入的功能,专门用于解决因 -- 被 git 重新定义而导致的参数注入风险。许多包管理器如 Bundler、Composer 和 Go 在调用 git 时,常因未正确处理以连字符开头的分支名而中招。文章深入探讨了从 Docker 到 Phabricator 的历史漏洞案例,分析了为何大多数工具仍停留在使用 -- 或检查输入格式的阶段,而非采用更安全的 --end-of-options。同时,对比了使用 libgit2 等库与直接调用 git 二进制文件的优劣,揭示了在安全与兼容性之间的艰难权衡。
代码在没有 --end-of-options 保护时看起来完全正确且运行正常,直到某个参数以连字符开头为止。
HN 评论区
120- metadat
有人知道 git 为什么早期就打破了长期以来使用 '--' 的惯例吗?这对人类用户来说简直是个噩梦。
记住那些特定于应用的特例简直是最糟糕的体验!
- yobert
所以我听明白了,我下一个分支应该命名为 '--' 对吧?:)
- bradley13
和几乎所有成功的系统一样:越来越多的特殊功能和边缘情况被加入。Git 已经变得荒谬地复杂了。
我不禁想问:对于那些遇到边缘情况的用户,告诉他们用其他方式解决问题难道不是更好吗?举个例子,文章里提到:为什么会有人创建一个以连字符开头的文件名?也许干脆别这么做。
- bombcar
这其实是 PowerShell 开始真正发光发热的少数几个地方之一——命令行把数据和命令混在一起,而我们本不该被迫这样做。
最可悲的是,甚至连 ASCII 都有字符能帮上忙,但因为键盘打不出来,没人用它们。
- Chinjut
“万物皆文本,一切通过文本完成”这一理念既有其优势,也有其劣势。
- epistasis
也许我漏掉了什么(今天过得有点长),但 '--' 难道不能同时用于这两种情况吗?
git cmd --options -- rev -- pathspec
这是完整的 revspec 和 pathspec。
git cmd --option -- rev --
这只是 revspec,排除了意外的选项,没有 pathspec。
git cmd --option revspec -- pathspec
而单个 '--' 的作用就和现在一样。
- angry_octet
当我在一篇名义上由人类撰写的文章中读到 Claude 风格的措辞 [1] 时,感觉就像蟑螂在脸上爬。
但这似乎不太公平,因为他们会不会是下意识地复述了 Claude 式的表达呢?
[1] “那确实是个代价。”
- _blk
> git log --end-of-options "$rev" -- "$path",
天哪,这时候我就真希望有个面向对象的 shell 了。PowerShell 固然不完美,但对象自带语义确实能很好地帮助区分这些情况(不过如果类型对读者来说不够清晰,可能也帮不到用户)。