PATH의 ~는 홈 디렉터리가 아닐 수 있음: 따옴표 없는 틸드가 확장되지 않는 bash 함정
- 틸드 확장은 따옴표 없는 단어의 맨 앞에서만 일어나서 export PATH="$PATH:~/.local/bin/"로 설정하면 홈이 아니라 현재 디렉터리 아래 ./~/.local/bin이 PATH에 추가됨
- nono 샌드박스 도구가 쓰기 가능한 PATH 항목으로 ~/.local/bin/을 경고하면서 이 문제가 드러남
- 수정은 $HOME을 쓰는 것이고, 따옴표 없이 PATH=$PATH:~/.local/bin처럼 쓰면 bash와 zsh에서는 =와 : 뒤에서 확장되지만 공백 하나에도 깨지기 쉬움
- echo "$PATH" | tr ':' '\n' | grep '~' 명령으로 PATH의 틸드 항목을 찾아볼 수 있음
Hacker News opinions
bash 함정 #238503인데 이건 zsh도 그렇고 사실 POSIX 표준 동작임. 단어 맨 앞의 따옴표 없는 ~만 $HOME으로 바뀌고 ~user, ~+, ~- 같은 것도 따로 있음.
홈 디렉터리 확인을 안 했다는 게 신기하네. PATH가 안 먹는데 그냥 넘어간 건가?
예제에서는 $HOME을 앞에 두는 게 낫다고 봄. 시스템 경로가 앞에 있어야 악성 스크립트가 sudo 같은 걸 가로채서 비밀번호 빼가는 걸 막을 수 있음.
경로에 [A-Za-z0-9._-]만 허용하면 골치 아픈 일이 확 줄어들 텐데. 다만 다른 언어 쓰는 사람은 어떡하냐는 반론이 바로 나오더라.
따옴표를 제대로 쓰는 게 답임. $ 들어간 건 큰따옴표로 감싸고 나머지 리터럴은 작은따옴표로 감싸면 대부분 해결됨.
POSIX 기준으로는 export PATH="$PATH:"~/.local/bin 처럼 따옴표를 나눠 쓰면 된다고 봄. 내 폰의 mksh에서는 실제로 그렇게 동작하더라.
Cursor가 repo 루트에 ~ 디렉터리를 만들어서 한참 치운 적 있음. 예약어를 몇 개 막아두는 것도 나쁘지 않다고 봄.
/bin/sh가 bash가 아닌 곳이 많으니까 bash 전용 문법을 쓸 거면 shebang을 #!/bin/bash로 명시해야 함. Debian 계열은 보통 dash임.
스크립트에서는 틸드 쓰지 말고 $HOME이나 $XDG_DATA_HOME처럼 명시적으로 쓰는 게 제일 안전함.