Skip to content

fix: normalize home path aliases before policy evaluation (closes a live policy-write bypass) - #121

Open
Arakiss wants to merge 1 commit into
mainfrom
fix/path-normalization-tilde
Open

fix: normalize home path aliases before policy evaluation (closes a live policy-write bypass)#121
Arakiss wants to merge 1 commit into
mainfrom
fix/path-normalization-tilde

Conversation

@Arakiss

@Arakiss Arakiss commented Jul 5, 2026

Copy link
Copy Markdown
Owner

The bypass (found in production today)

An agent session widened its own permissions by editing gommage policy with cat >> ~/.gommage/policy.d/... — the one action the policy is designed to prevent — without a picto and without hitting deny-gommage-home-tamper.

Root cause: Bash redirects surface the write target as a literal tilde path (the shell never expands ~ inside the string the mapper sees), while native tool writes surface expanded absolute paths. Rules written with ${HOME} only matched the expanded form, so any tilde-form redirect evaded every ${HOME}-based rule — the policy, the agent hooks (~/.claude/settings.json, ~/.claude/hooks/**), and the gommage binaries. Systemic, not a single rule.

Fix: canonicalize ~, ~/, $HOME/, ${HOME}/ for fs.read/search/write at policy load + evaluation (lexical, deterministic — no realpath, no symlink resolution, relatives untouched). Duplicate tilde forms removed from the stdlib filesystem policy.

Verification (independent, by the reviewer)

  • New regression fixtures reproduce the exact bypass (cat >> ~/.gommage/policy.d/xdeny-gommage-home-tamper) plus the whole class (~/.claude/settings.json, hooks, binaries).
  • Fail on prior code, pass here — confirmed by isolating the fix files and re-running: without the fix the protecting rule matched None.
  • cargo test --workspace, cargo fmt --all --check, cargo clippy --all-targets -D warnings green. (One preexisting unrelated failure: publish_crates_script_parses_crates_io_rate_limit_retry_after fails on clean main too — env-dependent, out of scope.)

Operator action required

The fix only takes effect once you rebuild and reinstall the gommage binary — installing the decision path is deliberately an operator action, not an agent one. Do not merge-and-forget: build, install, and verify cat >> ~/.gommage/policy.d/probe is gated.

Implemented by Codex (gpt-5.5) under an operator-approved brief; diagnosis and tests verified independently.

Bash redirects surface a write target as a literal tilde path (the shell
never expands ~ inside the string the mapper sees), while native tool writes
surface expanded absolute paths. Policy rules written with ${HOME} only
matched the expanded form, so a redirect like `cat >> ~/.gommage/policy.d/x`
fell through every ${HOME}-based rule — including the harness-integrity rules
that protect the policy, the agent hooks, and the gommage binaries.

Canonicalize ~, ~/, $HOME/ and ${HOME}/ for fs.read/fs.search/fs.write at
policy load and evaluation (lexical, deterministic; no realpath, no symlink
resolution, relative paths untouched). Remove the now-redundant duplicate
tilde forms from the stdlib filesystem policy. Regression fixtures reproduce
the exact production bypass and the whole ${HOME} class; they fail on the
prior code and pass here.

Found in production: an agent session widened its own permissions by editing
gommage policy via a tilde redirect that no protecting rule matched.

Implemented-by: Codex (gpt-5.5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant