mirror of
https://github.com/openai/codex.git
synced 2026-04-28 02:11:08 +03:00
execpolicy: add host_executable() path mappings (#12964)
## Why `execpolicy` currently keys `prefix_rule()` matching off the literal first token. That works for rules like `["/usr/bin/git"]`, but it means shared basename rules such as `["git"]` do not help when a caller passes an absolute executable path like `/usr/bin/git`. This PR lays the groundwork for basename-aware matching without changing existing callers yet. It adds typed host-executable metadata and an opt-in resolution path in `codex-execpolicy`, so a follow-up PR can adopt the new behavior in `unix_escalation.rs` and other call sites without having to redesign the policy layer first. ## What Changed - added `host_executable(name = ..., paths = [...])` to the execpolicy parser and validated it with `AbsolutePathBuf` - stored host executable mappings separately from prefix rules inside `Policy` - added `MatchOptions` and opt-in `*_with_options()` APIs that preserve existing behavior by default - implemented exact-first matching with optional basename fallback, gated by `host_executable()` allowlists when present - normalized executable names for cross-platform matching so Windows paths like `git.exe` can satisfy `host_executable(name = "git", ...)` - updated `match` / `not_match` example validation to exercise the host-executable resolution path instead of only raw prefix-rule matching - preserved source locations for deferred example-validation errors so policy load failures still point at the right file and line - surfaced `resolvedProgram` on `RuleMatch` so callers can tell when a basename rule matched an absolute executable path - preserved host executable metadata when requirements policies overlay file-based policies in `core/src/exec_policy.rs` - documented the new rule shape and CLI behavior in `execpolicy/README.md` ## Verification - `cargo test -p codex-execpolicy` - added coverage in `execpolicy/tests/basic.rs` for parsing, precedence, empty allowlists, basename fallback, exact-match precedence, and host-executable-backed `match` / `not_match` examples - added a regression test in `core/src/exec_policy.rs` to verify requirements overlays preserve `host_executable()` metadata - verified `cargo test -p codex-core --lib`, including source-rendering coverage for deferred validation errors
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
## Overview
|
||||
|
||||
- Policy engine and CLI built around `prefix_rule(pattern=[...], decision?, justification?, match?, not_match?)`.
|
||||
- This release covers the prefix-rule subset of the execpolicy language; a richer language will follow.
|
||||
- Policy engine and CLI built around `prefix_rule(pattern=[...], decision?, justification?, match?, not_match?)` plus `host_executable(name=..., paths=[...])`.
|
||||
- This release covers the prefix-rule subset of the execpolicy language plus host executable metadata; a richer language will follow.
|
||||
- Tokens are matched in order; any `pattern` element may be a list to denote alternatives. `decision` defaults to `allow`; valid values: `allow`, `prompt`, `forbidden`.
|
||||
- `justification` is an optional human-readable rationale for why a rule exists. It can be provided for any `decision` and may be surfaced in different contexts (for example, in approval prompts or rejection messages). When `decision = "forbidden"` is used, include a recommended alternative in the `justification`, when appropriate (e.g., ``"Use `jj` instead of `git`."``).
|
||||
- `match` / `not_match` supply example invocations that are validated at load time (think of them as unit tests); examples can be token arrays or strings (strings are tokenized with `shlex`).
|
||||
@@ -24,6 +24,26 @@ prefix_rule(
|
||||
)
|
||||
```
|
||||
|
||||
- Host executable metadata can optionally constrain which absolute paths may
|
||||
resolve through basename rules:
|
||||
|
||||
```starlark
|
||||
host_executable(
|
||||
name = "git",
|
||||
paths = [
|
||||
"/opt/homebrew/bin/git",
|
||||
"/usr/bin/git",
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
- Matching semantics:
|
||||
- execpolicy always tries exact first-token matches first.
|
||||
- With host-executable resolution disabled, `/usr/bin/git status` only matches a rule whose first token is `/usr/bin/git`.
|
||||
- With host-executable resolution enabled, if no exact rule matches, execpolicy may fall back from `/usr/bin/git` to basename rules for `git`.
|
||||
- If `host_executable(name="git", ...)` exists, basename fallback is only allowed for listed absolute paths.
|
||||
- If no `host_executable()` entry exists for a basename, basename fallback is allowed.
|
||||
|
||||
## CLI
|
||||
|
||||
- From the Codex CLI, run `codex execpolicy check` subcommand with one or more policy files (for example `src/default.rules`) to check a command:
|
||||
@@ -32,6 +52,15 @@ prefix_rule(
|
||||
codex execpolicy check --rules path/to/policy.rules git status
|
||||
```
|
||||
|
||||
- To opt into basename fallback for absolute program paths, pass `--resolve-host-executables`:
|
||||
|
||||
```bash
|
||||
codex execpolicy check \
|
||||
--rules path/to/policy.rules \
|
||||
--resolve-host-executables \
|
||||
/usr/bin/git status
|
||||
```
|
||||
|
||||
- Pass multiple `--rules` flags to merge rules, evaluated in the order provided, and use `--pretty` for formatted JSON.
|
||||
- You can also run the standalone dev binary directly during development:
|
||||
|
||||
@@ -52,6 +81,7 @@ cargo run -p codex-execpolicy -- check --rules path/to/policy.rules git status
|
||||
"prefixRuleMatch": {
|
||||
"matchedPrefix": ["<token>", "..."],
|
||||
"decision": "allow|prompt|forbidden",
|
||||
"resolvedProgram": "/absolute/path/to/program",
|
||||
"justification": "..."
|
||||
}
|
||||
}
|
||||
@@ -62,6 +92,7 @@ cargo run -p codex-execpolicy -- check --rules path/to/policy.rules git status
|
||||
|
||||
- When no rules match, `matchedRules` is an empty array and `decision` is omitted.
|
||||
- `matchedRules` lists every rule whose prefix matched the command; `matchedPrefix` is the exact prefix that matched.
|
||||
- `resolvedProgram` is omitted unless an absolute executable path matched via basename fallback.
|
||||
- The effective `decision` is the strictest severity across all matches (`forbidden` > `prompt` > `allow`).
|
||||
|
||||
Note: `execpolicy` commands are still in preview. The API may have breaking changes in the future.
|
||||
|
||||
Reference in New Issue
Block a user