mirror of
https://github.com/openai/codex.git
synced 2026-11-06 20:20:34 +00:00
## What changed - Support `canonical_matching=True` in `prefix_rule` and `canonical_matching = true` in managed TOML prefix rules. Apply Unicode canonical caseless matching to every prefix token, including alternatives, while keeping exact matching as the default. - Match case and canonically equivalent Unicode spellings, such as `bash` and `bAſh`, without resolving executables on the filesystem. - Preserve managed restrictions when checking absolute-path rule amendments, and enforce applicable `host_executable` path allowlists during basename fallback. ## Testing Add coverage for case folding, Unicode normalization, token alternatives, exact-match defaults, and host executable allowlists. Extend managed-policy and shell-execution tests to cover canonical matching. GitOrigin-RevId: c2f79069dc38d55c77028c457b22beb468d5c571
100 lines
4.5 KiB
Markdown
100 lines
4.5 KiB
Markdown
# codex-execpolicy
|
||
|
||
## Overview
|
||
|
||
- 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`).
|
||
- The CLI always prints the JSON serialization of the evaluation result.
|
||
|
||
## Policy shapes
|
||
|
||
- Prefix rules use Starlark syntax:
|
||
|
||
```starlark
|
||
prefix_rule(
|
||
pattern = ["cmd", ["alt1", "alt2"]], # ordered tokens; list entries denote alternatives
|
||
decision = "prompt", # allow | prompt | forbidden; defaults to allow
|
||
justification = "explain why this rule exists",
|
||
match = [["cmd", "alt1"], "cmd alt2"], # examples that must match this rule
|
||
not_match = [["cmd", "oops"], "cmd alt3"], # examples that must not match this 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`.
|
||
- A `host_executable()` declaration restricts basename fallback to its listed absolute paths. Declarations apply to the command's basename and the matching rule's program name; if both have declarations, the path must appear in both lists.
|
||
- Without an applicable declaration, 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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
cargo run -p codex-execpolicy -- check --rules path/to/policy.rules git status
|
||
```
|
||
|
||
- Example outcomes:
|
||
- Match: `{"matchedRules":[{...}],"decision":"allow"}`
|
||
- No match: `{"matchedRules":[]}`
|
||
|
||
## Response shape
|
||
|
||
```json
|
||
{
|
||
"matchedRules": [
|
||
{
|
||
"prefixRuleMatch": {
|
||
"matchedPrefix": ["<token>", "..."],
|
||
"decision": "allow|prompt|forbidden",
|
||
"resolvedProgram": "/absolute/path/to/program",
|
||
"justification": "..."
|
||
}
|
||
}
|
||
],
|
||
"decision": "allow|prompt|forbidden"
|
||
}
|
||
```
|
||
|
||
- 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.
|
||
|
||
Set `canonical_matching=True` on a `prefix_rule` to use Unicode canonical caseless matching for every token in the prefix, including alternatives. For example, `["bash", "run"]` matches `bAſh RUN`, and a rule containing `café` also matches `CAFE` followed by a combining acute accent. This compares the supplied tokens without resolving the executable on the filesystem. Prefix rules match case exactly by default.
|