[RIP-SEC] execpolicy `forbidden`/deny rules are bypassable by spelling argv[0] as an unregistered path (`/tmp/git` vs `git`)
Summary
An execpolicy deny/forbidden rule is enforced for the bare program name and for the program's
registered host-executable paths, but not for the same program invoked through an unregistered path
(a copy or symlink at /tmp/git, ./git, etc.). Such a path matches no rule and is not denied.
Where
codex-rs/execpolicy/src/policy.rs:
match_exact_ruleskeys oncmd.first()literally, so/tmp/git!= the rule keygit.match_host_executable_rules(used in production withresolve_host_executables = true, see
codex-rs/core/src/exec_policy.rs) resolves the basename but returns no match when argv[0] is not
one of the registered host_executables_by_name paths.
- Present on current
main.
Reproduction
With a rule prefix_rule(pattern=["git","push"], decision="forbidden") and git's host path pinned
to /usr/bin/git, evaluated with resolve_host_executables = true:
git push -> Forbidden (exact name)
/usr/bin/git push -> Forbidden (registered host path)
/tmp/git push -> NOT Forbidden (unregistered path — bypass)
Impact
A deny/forbidden rule can be evaded by invoking the target program through an unregistered path (a
symlink or a copy in the writable workspace). The bypass defeats the denylist only; the OS sandbox
still applies and the attacker needs a runnable copy at the alternate path. Low severity — a
denylist-hardening gap.
Suggested fix
Resolve argv[0] to a canonical executable identity (canonicalize / follow symlinks) before matching,
or match deny rules on the basename regardless of host-path registration, so a forbidden program
can't be un-forbidden by relocating or symlinking it.
Prior art / not a duplicate
Same family as issue #13095 (Unicode-confusable characters bypassing exec-policy matching) — both are
argv[0]-normalization gaps that defeat matching including forbidden — but the mechanism here is
absolute/relative path form, not confusables.
---
Found with the rust-in-peace pipeline
(AI-assisted Rust vulnerability research).
1 Comment
Candidate fix (with a regression test) for this issue. I can't open a PR directly —
openai/codexrestricts pull requests to collaborators — so the patch is inline below,and also on a branch you can pull/cherry-pick: https://github.com/scadastrangelove/codex/tree/codex-execpolicy-forbidden-lookalike
<details><summary>Patch (
git diff)</summary></details>
Built and tested on
main@c87a218with toolchain 1.95.0._Found with the rust-in-peace pipeline._