Skip to content

Instantly share code, notes, and snippets.

@fragmede
Last active December 23, 2025 01:25
Show Gist options
  • Select an option

  • Save fragmede/96f35225c29cf8790f10b1668b849af7 to your computer and use it in GitHub Desktop.

Select an option

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
#!/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