Тильда в PATH — это не всегда ваш домашний каталог

· Linux и open source
Автор обнаружил, что строка `export PATH="$PATH:~/.local/bin/"` в кавычках не раскрывает тильду в путь к дому — и показал, почему это опасно.

cover.svg

Автор возился с инструментом для песочницы агентов nono и получил от него подозрительное предупреждение: песочница может писать в элемент PATH ~/.local/bin/. Разбирательство привело к давней ловушке оболочки, о которой стоит знать каждому, кто правит свои .bashrc или .zshrc.

В чём подвох

Строка вида

export PATH="$PATH:~/.local/bin/"

не превратит тильду в путь к домашнему каталогу. Раскрытие тильды в $HOME происходит только для неэкранированных символов, а внутри двойных кавычек тильда остаётся самой собой. В итоге в PATH добавляется не /home/<user>/.local/bin/, а буквальный ./~/.local/bin/ — относительный путь к каталогу с именем «тильда» в текущей директории.

Документация bash это подтверждает: тильда-префикс раскрывается, если слово начинается с неэкранированной тильды, в том числе сразу после = или : в присваивании переменной. Ключевое слово — «неэкранированной».

Почему это небезопасно

Автор приводит наглядную демонстрацию. Он создаёт каталог ./~/.local/bin/, кладёт туда скомпилированный бинарник kek, а затем запускает PATH="~/.local/bin/" kek — и программа находится и выполняется. Домашний каталог при этом вообще не задействован: оболочка нашла исполняемый файл в подкаталоге текущей директории.

Отсюда и тревога песочницы: если в PATH оказывается элемент, относящийся к текущему каталогу, любой, кто сможет туда что-то записать, фактически получает возможность подсунуть вам исполняемый файл.

Как проверить и починить

Быстрая проверка:

echo "$PATH" | grep -- '~'

или, чтобы видеть каждый элемент отдельной строкой:

echo "$PATH" | tr ':' '\n' | grep '~'

Если что-то выводится — пора заглянуть в .bashrc, .zshrc или .profile и заменить тильду на $HOME:

export PATH="$PATH:$HOME/.local/bin/"

Любопытно, что вариант без кавычек — export PATH=$PATH:~/.local/bin — в bash и zsh всё-таки работает, потому что тильда раскрывается в присваиваниях после = и после каждого :. Но полагаться на это хрупко: достаточно пробела, и присваивание сломается. Автор отдельно поблагодарил инструмент nono за предупреждение — и пообещал прислать PR, чтобы сделать его сообщение чуть подробнее.


Источник: Hacker News

Комментарии

Войдите, чтобы комментировать.

  • Пока нет комментариев.