Skip to content

fix(codex): mirror execpolicy rules into managed Codex homes - #24432

Closed
u-ichi wants to merge 2 commits into
stablyai:mainfrom
u-ichi:fix/codex-mirror-rules
Closed

u-ichi wants to merge 2 commits into
stablyai:mainfrom
u-ichi:fix/codex-mirror-rules

Conversation

@u-ichi

@u-ichi u-ichi commented Oct 1, 2026 •

Copy link
Copy Markdown

ELI5

Codex has a file of rules that says which commands are always allowed, need a prompt, or are forbidden. When Orca starts Codex, it gives Codex its own home folder and links your usual Codex settings into it, but it forgot to link the rules folder. So Codex in Orca behaves as if you had no rules. This PR links the rules folder too.

What Changed

  • Before: an Orca-launched Codex session uses a managed CODEX_HOME that has no rules/ directory. Codex loads execpolicy rules only from $CODEX_HOME/rules/, so the user's ~/.codex/rules/*.rules are ignored. Commands covered by an allow rule run in the sandbox and fail (then ask for escalation), and forbidden/prompt rules do not apply.
  • After: rules is added to CODEX_SYSTEM_RESOURCE_ENTRIES, so syncSystemCodexResourcesIntoManagedHome links <managed home>/rules -> ~/.codex/rules (or makes an owned fallback copy where symlinks fail), the same way it already handles hooks, prompts and AGENTS.md. This applies to the shared runtime home and to per-account homes.

Why

The rules are user-level Codex configuration in the same sense as hooks and skills, which Orca already shares into the managed home. Reusing the existing mirroring keeps one source of truth in ~/.codex and needs no new code path.

Alternatives considered:

  • Copying rules into each managed home: they would go stale when the user edits ~/.codex/rules, and the existing mirror already handles refresh and ownership.
  • Mirroring only default.rules: users and tools also keep other .rules files in that directory, and Codex reads every *.rules file there.

Behavior to be aware of: when the user picks "always allow" in an Orca-launched Codex session, Codex writes to $CODEX_HOME/rules/default.rules, which now resolves to ~/.codex/rules/default.rules. That saved rule is then shared with plain Codex and other accounts, the same as edits to shared skills or hooks. If a managed home already has its own rules directory (for example from such a save before this change), the existing logic leaves it in place and does not replace it.

Linked Issue

Fixes #24431

Visual Proof

N/A — no UI change. The change only adds one directory to the set of resources linked into the managed Codex home.

Testing

  • Added a unit test in src/main/codex/codex-home-paths.test.ts that syncs a per-account home and checks that rules/ is linked to (or copied from) ~/.codex/rules.

  • pnpm test src/main/codex/codex-home-paths.test.ts: 19 passed. With 'rules' removed from the list, only the new test fails (ENOENT ... home/rules/default.rules).

  • pnpm tc:node, oxlint and oxfmt --check on the changed files: pass.

  • Manual check on macOS before the change: in an Orca Codex tab, git add covered by an allow rule and git stage (no rule) both failed with index.lock: Operation not permitted, and the managed home had no rules entry.

  • Manual check after the change: not done; it needs an Orca build with this change.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Author

X: @u1

AI Disclosure

Investigation, the code change, the test and this description were prepared with Claude Code (Claude Opus 5.5) and reviewed by me.

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Security: this restores the user's own forbidden/prompt rules inside Orca, which were silently not applied. Cross-platform: uses the existing mirror, which already handles Windows junctions and copy fallback. SSH/remote and WSL: unchanged; WSL launches still copy only AGENTS.md and config.toml (syncWslConfigAndGlobalInstructionsForLaunch), so rules are not mirrored there by this PR.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

Orca-launched Codex uses a managed CODEX_HOME, and Codex loads
execpolicy .rules only from $CODEX_HOME/rules. The managed home linked
skills, hooks, prompts and AGENTS.md from ~/.codex but not rules, so the
user's allow/prompt/forbidden rules did not apply in Orca sessions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@u-ichi
u-ichi marked this pull request as ready for review October 2, 2026 08:00
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 4132adae-4f82-4bd7-8a2d-eceeadeb5f14

📥 Commits

Reviewing files that changed from the base of the PR and between b3f1e4a and 89456cd.

📒 Files selected for processing (1)
  • src/main/codex/codex-home-paths.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/codex/codex-home-paths.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The managed-home resource list now includes rules, so synchronization includes system Codex rules alongside existing resources. A test creates rules/default.rules, synchronizes it into an explicit per-account home, and checks the file contents and link behavior.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 89456

User rules are mirrored into managed homes when the destination is absent. Existing directories remain untouched as intended; no issue identified here prevents merging after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b3f1e

The policy source remains the local user's Codex configuration, and account credentials are not added to the shared resources. Risk is bounded, but copied rules have weaker persistence and failure behavior than linked rules.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The supported exposure is command-policy inheritance by shared and per-account managed host homes belonging to the same local user. It is not evidence of new remote, cross-user, or credential authority.

Trust Boundaries and Controls

  • observed — The mirror uses a fixed local-user source and preserves present targets that are not recognized as owned fallback copies. Source-removal cleanup checks ownership before deleting a managed resource. Existing tests also assert that authentication, sessions, and history are not included in this resource mirror.

Resilience and Maintainability Implications

  • inferred — Fallback rules are source-refreshed configuration rather than durable managed-home state: edits made only to an owned copy can be overwritten at the next synchronization. The inspected launch paths do not check a rules-mirroring success result. These limitations affect the new policy integration, but base already lacked the system rules and therefore does not establish a newly weakened security boundary.

Hardening Proposals

  • proposed — Define the writable-policy ownership contract for fallback copies and validate session-write persistence across refresh. If mirrored rules are intended as a mandatory security guarantee, consider transactional replacement and an explicit launch decision when policy synchronization fails.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR satisfies the coding requirements in [#24431]. It adds rules to CODEX_SYSTEM_RESOURCE_ENTRIES. The existing synchronization logic therefore mirrors $CODEX_HOME/rules into shared and per-a…
Out of Scope Changes check ✅ Passed The changes stay within [#24431]. The source change adds only the missing Codex rules resource. The test covers the required synchronization behavior. No unrelated product behavior or files are iden…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Title check ✅ Passed The title clearly summarizes the main change: mirroring execpolicy rules into managed Codex homes.
Description check ✅ Passed The description covers the change, motivation, linked issue, visual-proof requirement, testing, AI disclosure, and relevant compatibility notes. It also states that post-change manual testing was not …
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one edge-case note inline.

Reviewed changes

  • Mirror rules into managed Codex homes: 'rules' is added to CODEX_SYSTEM_RESOURCE_ENTRIES, so syncSystemCodexResourcesIntoManagedHome links (or copies, where symlinks fail) the user's ~/.codex/rules into the shared runtime home and per-account homes. This restores the allow/prompt/forbidden execpolicy rules an Orca-launched Codex previously ignored.
  • Test: a new per-account-home test asserts rules/default.rules is readable through the managed home and points at the system rules dir when linked.

ℹ️ Nitpicks

  • codex-home-paths.ts:32 — the // Why says Codex loads .rules "only from $CODEX_HOME/rules". Per the Codex docs, rules/ is scanned under every active config layer (Team Config and trusted project .codex/rules too); consider "including" rather than "only from".

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

'themes',
'prompts',
// Why: Codex loads execpolicy `.rules` only from `$CODEX_HOME/rules`.
'rules',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Windows copy-fallback path (when directory symlink/junction creation fails), linkSystemCodexResource treats rules as a refreshable owned copy: it deletes the target and re-copies from ~/.codex/rules on every launch, with no content-match short-circuit like AGENTS.md gets. Because Codex writes newly saved "always allow" rules into $CODEX_HOME/rules/default.rules, those rules would live only in the managed copy and be discarded on the next sync — and never reach ~/.codex/rules. This only matters where the fallback is actually taken, so it may be moot if junctions always succeed for local NTFS homes.

Technical details
# `rules` is the first writable resource in a delete-and-recopied fallback copy

## Affected sites
- `src/main/codex/codex-home-paths.ts:33` — `rules` added to the mirrored entries.
- `src/main/codex/codex-home-paths.ts:147-165` — owned fallback copies for non-`AGENTS.md` entries are unconditionally `rmSync`'d and recreated each sync; only `AGENTS.md` short-circuits on an unchanged read.
- `src/main/codex/codex-managed-home-resource-copy-marker.ts:54` — ownership keys on source path + non-symlink, so a Codex-modified copy is still "owned" and replaced.

## Required outcome
- A rule Codex saves into the managed home should survive a later sync, or the managed and user copies should converge.

## Suggested approach
- Skip the refresh for `rules` when the difference is Codex-added content, or merge new/changed `*.rules` back into `~/.codex/rules` before replacing the copy.

## Open questions for the human
- Is the fallback reachable on Windows in practice, or does directory `junction` creation always succeed for local NTFS managed homes? If fallback copies are expected, auto-saved rules are lost on the next launch.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. The nitpick on the comment wording is fixed in 89456cd.

On the copy fallback: rules is a directory, so on Windows it goes through symlinkSync(..., 'junction'). Directory junctions do not need Developer Mode or admin rights, so the fallback copy is only taken when even a junction cannot be created (for example, a managed home on a volume that does not support junctions). In that case the same delete-and-recopy refresh already applies to the other mirrored directories, and Codex-saved "always allow" rules would be lost as you describe.

I kept this PR to the one-line fix for the common case, where the managed home links to ~/.codex/rules and saved rules land in the user's own file. If maintainers prefer, I can follow up by skipping the refresh of an owned rules copy when its contents differ from the source, so saved rules are not discarded.

Codex also reads rules from Team Config and trusted project layers; the
managed home only needs the user layer at $CODEX_HOME/rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nwparker

nwparker commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Thanks for reporting this and for the clear reproduction and original fix. The missing global rules are a real bug. I've opened #26086 with you credited as co-author. It imports global rules alongside existing account rules while keeping new account approvals in that account's default.rules. Linking the whole directory would share those approvals globally, and an existing account rules directory would still hide global restrictions. The replacement also handles interrupted updates and refuses conflicting files instead of overwriting them.

I'm closing this PR as superseded by #26086; #24431 stays open until the fix merges. If you disagree or spot a case we've missed, please reopen this PR, or reply here if GitHub won't let you and we'll reopen it for you. We'll take a look sooner this time.

@nwparker nwparker closed this Oct 7, 2026
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.

[Bug]: Codex sessions launched by Orca ignore the user's execpolicy rules in ~/.codex/rules

2 participants