SafeExec is a Bash-based safety layer that protects Ubuntu/Debian servers, WSL, and macOS from accidental (or hallucinated) destructive commands run by AI agents (Codex/GPT) or humans.
It intercepts dangerous commands (like rm -rf or git reset --hard) and enforces an interactive confirmation gate via a real terminal input. This prevents pipes/non-interactive execution from bypassing safety checks.
-
TTY-Based Confirmation Gate
- Requires the user to type
confirmto proceed. - Reads from a real terminal device (not stdin), so
echo confirm | ...doesn’t bypass it. - If there is no usable TTY, the command is blocked (exit
126).
- Requires the user to type
-
WSL/Codex Harness Safety
- Some WSL/Codex setups have
/dev/ttypresent but unusable (EACCES). SafeExec probe-opens it. - If there is no usable terminal input, SafeExec blocks rather than “half prompting” inside a TUI.
- Some WSL/Codex setups have
-
Destructive
rmGating- Intercepts only when both recursive + force flags are present:
rm -rf ...,rm -fr ...,rm --recursive --force ...
- Intercepts only when both recursive + force flags are present:
-
Granular
gitGating- Always gated:
git reset,git revert,git checkout,git restore - Gated if forced:
git clean -f/git clean --force - Gated if destructive:
git switch -f,git switch --discard-changes - Gated stash ops:
git stash drop,git stash clear,git stash pop
- Always gated:
-
Sudo Protection
- Installs
/etc/sudoers.d/safeexecto prepend SafeExec intosecure_path, ensuringsudo rm -rf ...andsudo git ...are intercepted (soft mode).
- Installs
-
macOS Homebrew Git Coverage
- Apple Silicon (default Homebrew prefix):
gitusually resolves from/opt/homebrew/bin/git. SafeExec installs a Homebrew git shim there, backing up the original to:/opt/homebrew/bin/git.safeexec.real
- Intel macOS (common Homebrew prefix):
gitmay resolve from/usr/local/bin/gitwhich is often a Homebrew symlink into Cellar. SafeExec will detect this case and safely back it up to:/usr/local/bin/git.safeexec.realthen install the SafeExec shim at/usr/local/bin/git.
- Apple Silicon (default Homebrew prefix):
-
Ubuntu/Debian/WSL Hard Mode (recommended for Codex/agents)
- Codex/non-interactive harnesses can bypass PATH via:
command -p rm, absolute paths (/usr/bin/rm), or restricted env PATH.
- Hard mode uses
dpkg-divertto replace/usr/bin/rmand/usr/bin/gitwith safe dispatchers, catching non-interactive shells, command -p, and absolute paths.
- Codex/non-interactive harnesses can bypass PATH via:
-
Quick Toggle
safeexec -offdisables prompts per-usersafeexec -onre-enablessafeexec statusprints current state- Global toggle:
sudo safeexec -off --global
-
Audit Logging
- Logs blocked + confirmed actions to syslog via
logger(if available).
- Logs blocked + confirmed actions to syslog via
chmod +x safeexec.sh
sudo ./safeexec.sh install
hash -rchmod +x safeexec.sh
sudo ./safeexec.sh install
hash -rHard mode is what makes SafeExec apply to non-interactive harness execution and cases where PATH is bypassed.
sudo ./safeexec.sh install
sudo ./safeexec.sh install-hard
hash -rIf a dangerous command is attempted, execution is paused:
rm -rf /var/www/html
[SAFEEXEC] DESTRUCTIVE COMMAND INTERCEPTED:
rm -rf /var/www/html
Type "confirm" to execute:git reset --hard HEAD~1
[SAFEEXEC] DESTRUCTIVE COMMAND INTERCEPTED:
git reset --hard HEAD~1
Type "confirm" to execute:To proceed, type confirm + Enter. Any other input (or Ctrl+C) cancels with exit code 130.
If SafeExec cannot access a usable terminal input, it blocks with exit code 126.
Per-user:
safeexec -off
safeexec status
safeexec -onGlobal (requires sudo):
sudo safeexec -off --global
sudo safeexec -on --global
sudo safeexec status --globalOne-command bypass (no prompting for that single invocation):
SAFEEXEC_DISABLED=1 rm -rf /tmp/junk
SAFEEXEC_DISABLED=1 git reset --hard- Installs wrappers at:
/usr/local/safeexec/bin/rm/usr/local/safeexec/bin/git
- Installs shims (symlinks) at:
/usr/local/bin/rm→/usr/local/safeexec/bin/rm/usr/local/bin/git→/usr/local/safeexec/bin/git
- Installs sudo
secure_pathrule:/etc/sudoers.d/safeexec
Because Homebrew’s PATH often wins, SafeExec also installs:
/opt/homebrew/bin/gitshim → calls SafeExec wrapper- Backup stored as:
/opt/homebrew/bin/git.safeexec.real
If Homebrew owns /usr/local/bin/git as a symlink into Cellar (common on Intel macOS),
SafeExec will:
- Move the existing symlink to:
/usr/local/bin/git.safeexec.real - Install its shim at:
/usr/local/bin/git
Rollback:
sudo rm /usr/local/bin/git
sudo mv /usr/local/bin/git.safeexec.real /usr/local/bin/git
hash -r- Diverts real binaries:
/usr/bin/rm→/usr/bin/rm.safeexec.real/usr/bin/git→/usr/bin/git.safeexec.real
- Installs wrappers at the original paths (
/usr/bin/rm,/usr/bin/git) that dispatch into:/usr/local/safeexec/bin/rm/usr/local/safeexec/bin/git
Result: even command -p rm, absolute paths, and minimal environment shells are gated.
./safeexec.sh statusApple Silicon:
which git: /opt/homebrew/bin/git
effective gate git: [YES] (homebrew shim)
Intel (example):
which git: /usr/local/bin/git
effective gate git: [YES]
rm hard-mode: [YES] (/usr/bin/rm)
git hard-mode: [YES] (/usr/bin/git)
/bin/rm -rf /tmp/junk
/usr/bin/git reset --hard/opt/homebrew/bin/git.safeexec.real reset --hardHard mode is designed to be hard to bypass. If you must bypass in an emergency:
- Disable globally:
sudo safeexec -off --global
- Or uninstall hard mode:
sudo ./safeexec.sh uninstall-hard
Soft mode uninstall:
sudo ./safeexec.sh uninstallHard mode uninstall (if enabled):
sudo ./safeexec.sh uninstall-hard- Any solution can be bypassed by explicitly executing the real diverted binaries (hard mode):
/usr/bin/rm.safeexec.real/usr/bin/git.safeexec.real
- Under full-screen TUIs (like Codex on Windows), prompts may appear “misplaced” due to UI redraw. SafeExec will block if it cannot read from a real terminal input.