Đừng bao giờ dùng dấu ngã (~) trong biến PATH của bạn
Một lỗi cấu hình tưởng chừng vô hại trong file .bashrc hay .zshrc có thể khiến dấu ngã (~) không được mở rộng thành thư mục home, dẫn đến việc hệ thống tìm kiếm lệnh sai chỗ và mở ra lỗ hổng bảo mật nghiêm trọng.

Có những lỗi cấu hình tưởng chừng nhỏ nhặt nhưng lại âm thầm tạo ra lỗ hổng bảo mật trong hệ thống của bạn. Một trong số đó là việc sử dụng dấu ngã ~ trong biến môi trường PATH — thói quen phổ biến của không ít lập trình viên và quản trị viên hệ thống.
Câu chuyện bắt đầu khi một người dùng đang thử nghiệm công cụ sandbox nono thì nhận được cảnh báo đáng ngờ: các mục trong PATH mà sandbox có thể ghi vào bao gồm ~/.local/bin/. Cảnh báo này hé lộ một vấn đề mà nhiều người vô tình mắc phải mà không hề hay biết.
Dấu ngã không hoạt động như bạn nghĩ
Nhiều người thường thêm thư mục cá nhân vào PATH bằng cách viết thế này trong ~/.bashrc hoặc ~/.zshrc:
export PATH="$PATH:~/.local/bin/"
Nghe có vẻ hợp lý, nhưng thực tế đây là một sai lầm. Dấu ngã chỉ được mở rộng thành đường dẫn home (hoặc $HOME) khi nó nằm trong ngữ cảnh không được trích dẫn (unquoted). Theo tài liệu của Bash:
Nếu một từ bắt đầu bằng ký tự ngã chưa được trích dẫn ('~'), tất cả các ký tự cho đến dấu gạch chéo chưa được trích dẫn đầu tiên (…) được coi là tiền tố ngã (tilde-prefix).
Bash kiểm tra từng phép gán biến để tìm tiền tố ngã chưa trích dẫn ngay sau dấu ':' hoặc dấu '=' đầu tiên, rồi thực hiện việc mở rộng ngã trong những trường hợp đó. Vấn đề là khi bạn đặt ~ bên trong cặp dấu ngoặc kép "...", việc mở rộng này không diễn ra.
Kết quả là thay vì có /home/ten-ban/.local/bin/ trong PATH, bạn lại nhận được ./~/.local/bin/ — một thư mục tương đối tính từ vị trí hiện tại của bạn.
Kịch bản nguy hiểm có thể xảy ra
Để minh họa mức độ nghiêm trọng, hãy xem thí nghiệm đơn giản sau. Giả sử kẻ tấn công hoặc một tập lệnh độc hại tạo ra một thư mục có tên ~ trong thư mục hiện hành:
$ mkdir -p ./~/.local/bin/
$ printf '#include \nint main() { puts("hello"); }' > a.c
$ gcc a.c -o ./~/.local/bin/kek
$ PATH="~/.local/bin/" kek
hello
Minh họa cảnh báo về dấu ngã trong đường dẫn PATH
Như bạn thấy, tệp nhị phân kek vẫn được tìm thấy và thực thi từ ./~/.local/bin/ — thư mục home thực sự chưa bao giờ được sử dụng. Đây là cơ chế hoàn hảo để thực thi mã tùy ý nếu kẻ tấn công kiểm soát được thư mục làm việc hiện tại của bạn.
Cách kiểm tra và khắc phục
Bạn có thể nhanh chóng kiểm tra xem mình có mắc phải lỗi này không bằng lệnh:
$ echo "$PATH" | grep -- '~'
Hoặc để xem từng mục trên một dòng riêng:
$ echo "$PATH" | tr ':' '\n' | grep '~'
~/.local/bin/
Minh họa dấu ngã trong biến PATH
Nếu lệnh in ra bất kỳ kết quả nào, hãy lập tức sửa lại file .bashrc, .zshrc hoặc .profile. Cách khắc phục rất đơn giản — thay dấu ngã bằng biến $HOME:
export PATH="$PATH:$HOME/.local/bin/"
Một lưu ý tinh tế
Đáng chú ý là phiên bản không trích dẫn như export PATH=$PATH:~/.local/bin lại hoạt động đúng trong cả Bash và Zsh, bởi vì việc mở rộng dấu ngã cũng được thực hiện trong phép gán biến sau dấu '=' và sau mỗi dấu ':'. Tuy nhiên, việc dựa vào hành vi này là khá mong manh — chỉ cần một khoảng trắng xuất hiện cũng đủ phá vỡ toàn bộ phép gán biến.
Vì vậy, lời khuyên an toàn nhất vẫn là luôn sử dụng $HOME hoặc ${HOME} thay vì ~ khi cấu hình PATH. Đây là một trong những thói quen nhỏ nhưng đóng góp quan trọng vào việc bảo vệ môi trường phát triển và máy chủ của bạn trước những rủi ro không đáng có.
Cũng cần ghi nhận công cụ sandbox nono vì đã cảnh báo về vấn đề này — dù thông báo vẫn có thể chi tiết hơn để người dùng dễ nhận biết mức độ nghiêm trọng.

