别在 PATH 里用波浪号(~):nono 沙箱工具曝出路径展开陷阱
Don't Put Tilde In Your Path
在 .bashrc/.zshrc 中写 `export PATH="$PATH:~/.local/bin/"` 时,引号内的 ~ 不会展开为家目录,PATH 里实际加入的是相对路径 ./~/.local/bin/,导致二进制从该目录被执行而非家目录。nono agent 沙箱工具会对此发出警告,修复方法是改用 $HOME。可用 `echo "$PATH" | grep -- '~'` 快速自查。
我当时正在试用 nono 这个 agent 沙箱工具,它给我弹出了一个警告:PATH entries the sandbox can write to: ~/.local/bin/ 看起来有点可疑。

换句话说,在你的 ~/.bashrc 或 ~/.zshrc 里这样做:
export PATH="$PATH:~/.local/bin/"
不会把 ~(波浪号)展开成主目录路径(也就是 $HOME),因为波浪号到主目录的展开只发生在未加引号的输入中,正如 bash 文档所说:
如果一个单词以未加引号的波浪号字符(‘~’)开头,那么直到第一个未加引号的斜杠(……)之前的所有字符都被视为波浪号前缀。(……)
Bash 会检查每个变量赋值中紧跟在‘:’或第一个‘=’之后的未加引号波浪号前缀,并在这些情况下执行波浪号展开。(……)
所以最终加到 PATH 里的不是 /home/<user>/.local/bin/,而是 ./~/.local/bin/ 加到了 PATH 里。
要修复这个问题,我们可以这样做:
export PATH="$PATH:$HOME/.local/bin/"
注意,未加引号的版本 export PATH=$PATH:~/.local/bin 在 Bash 和 Zsh 里其实是有效的,因为变量赋值中在 = 之后以及每个 : 之后也会执行波浪号展开。但依赖这一点很脆弱,因为比如一个空白字符就会破坏变量赋值。
这个问题在这里也能看到:
$ ls -la
total 0
drwxr-xr-x@ 2 dc staff 64 Oct 2 13:37 .
drwxr-x---+ 105 dc staff 3360 Oct 2 13:37 ..
$ mkdir -p ./~/.local/bin/
$ printf '#include <stdio.h>\nint main() { puts("hello"); }'>a.c; gcc a.c -o ./~/.local/bin/kek
$ PATH="~/.local/bin/" kek
hello
$ tree -f
.
├── ./~
│ └── ./~/.local
│ └── ./~/.local/bin
│ └── ./~/.local/bin/kek
└── ./a.c
4 directories, 2 files

如我们所见,kek 二进制文件是从 ./~/.local/bin/ 找到并执行的——主目录根本没有参与。
检查你的 PATH
你可以用下面的命令快速检查自己是否有这个问题:
$ echo "$PATH" | grep -- '~'
或者,想逐行查看每个条目:
$ echo "$PATH" | tr ':' '\n' | grep '~'
~/.local/bin/
如果它打印出了任何内容,就去修复你的 .bashrc/.zshrc/.profile,把 ~ 替换成 $HOME 吧 :)
顺便说一句,感谢 nono 工具对此发出警告——尽管这个警告本可以更详细一些(PR 马上就来)。
来源:Hacker News · disconnect3d.pl