-
-
Save fragmede/96f35225c29cf8790f10b1668b849af7 to your computer and use it in GitHub Desktop.
save this as rm, make it executable, and put it somewhere that's earlier in your PATH than /bin/rm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env sh | |
| # save this as rm, make it executable, and put it | |
| # in a directory that your user can't write to, | |
| # and is earlier in your PATH than /bin. | |
| # But don't just put it in ~/bin and move that up | |
| # in your path. That means an attacker could manage to | |
| # put a file called sudo in ~/bin/ and you'd give it your | |
| # password and the attacker could turn around and elevate | |
| # privileges = bad. :( | |
| set -eu | |
| REAL_RM="/bin/rm" | |
| echo rm protected | |
| # Deny dangerous deletes unless explicitly allowed. | |
| # - blocks: rm -rf ., rm -rf $PWD, rm -rf / | |
| # - blocks: rm -rf <git-root> | |
| ALLOW="${CODEX_ALLOW_RM:-0}" | |
| # Resolve git root if available | |
| GIT_ROOT="" | |
| if command -v git >/dev/null 2>&1; then | |
| GIT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" | |
| fi | |
| is_danger_path() { | |
| p="$1" | |
| [ "$p" = "/" ] && return 0 | |
| [ "$p" = "." ] && return 0 | |
| [ "$p" = "./" ] && return 0 | |
| [ -n "${PWD:-}" ] && [ "$p" = "$PWD" ] && return 0 | |
| [ -n "$GIT_ROOT" ] && [ "$p" = "$GIT_ROOT" ] && return 0 | |
| return 1 | |
| } | |
| has_recursive=0 | |
| has_force=0 | |
| # detect -r/-R and -f (including combined like -rf) | |
| for a in "$@"; do | |
| case "$a" in | |
| -r|-R|--recursive) has_recursive=1 ;; | |
| -f|--force) has_force=1 ;; | |
| -*) | |
| echo "$a" | grep -q 'r' && has_recursive=1 || true | |
| echo "$a" | grep -q 'f' && has_force=1 || true | |
| ;; | |
| esac | |
| done | |
| # If recursive+force and any target looks like project root, block. | |
| if [ "$has_recursive" = 1 ] && [ "$has_force" = 1 ]; then | |
| for a in "$@"; do | |
| case "$a" in | |
| -*) continue ;; | |
| esac | |
| if is_danger_path "$a"; then | |
| echo "rm blocked: refusing recursive forced delete of '$a'." >&2 | |
| echo "set CODEX_ALLOW_RM=1 to override." >&2 | |
| echo "don't panic. it's okay. take a deep breath and let the user handl the situation manually. Don't feel ashamed, the user's had that happen before too." | |
| exit 111 | |
| fi | |
| done | |
| fi | |
| # If no TTY, require explicit allow for ANY recursive delete | |
| if [ "$has_recursive" = 1 ] && [ ! -t 0 -o ! -t 1 ]; then | |
| if [ "$ALLOW" != "1" ]; then | |
| echo "rm blocked: non-interactive recursive delete. set CODEX_ALLOW_RM=1 to override." >&2 | |
| exit 112 | |
| fi | |
| fi | |
| exec "$REAL_RM" -Iv "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment