Skip to content

fix(codex): remove the trust Orca wrote for a worktree when it is removed - #24807

Open
Waynting wants to merge 2 commits into
stablyai:mainfrom
Waynting:fix/codex-worktree-trust-cleanup
Open

Waynting wants to merge 2 commits into
stablyai:mainfrom
Waynting:fix/codex-worktree-trust-cleanup

Conversation

@Waynting

@Waynting Waynting commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

ELI5

Before Orca starts Codex in a worktree, it tells Codex in advance that it can trust that folder. Until now Orca never took that back, so the trust stayed after the worktree was deleted. Now, when a worktree is removed, Orca removes the trust it added for it. Trust you set up yourself stays.

What Changed

Before: every Codex launch into a new folder added this to config.toml:

[projects."<path>"]
trust_level = "trusted"

Removing the worktree (orca worktree rm or Delete in the sidebar) left the entry in place. The config mirror had also copied it into every managed account home (codex-accounts/<id>/home/config.toml), and the mirror only adds tables, never removes them. Over time these files filled up with trust for paths that no longer exist. Worktree names get reused (-r1, -r2, …), so a stale entry would also trust whatever later appeared at that path.

After: removing a local workspace removes the trust Orca wrote for it, both from the files Orca wrote to and from the account-home copies.

How it works:

  1. Ledger. When pre-trust creates a table that was not there before, Orca records the config file and the path in codex-runtime-home/project-trust-ledger.json. If the table already existed, it belongs to the user and is never recorded.
  2. Revocation. Both removal paths call the cleanup once a workspace's metadata is gone: the runtime path (purgeRemovedWorktree, used by the CLI and by interrupted removals that resume) and the UI path (removeWorktreeMetadataAndTransientState, used by worktree, folder-workspace and forget removals). For each recorded path at or below the removed root, Orca deletes the table only if it still contains exactly what Orca wrote. Every write goes through the existing per-file Codex config lock.
  3. Account homes. Once neither ~/.codex nor the runtime home still trusts the path (no table, or an explicit untrusted), the path goes into a pending list in the ledger. This happens in the same atomic write that stops tracking it. The mirrored copies are then deleted from each owned account home, again only if they still contain exactly what Orca wrote. If an account home or a source config cannot be read, nothing is deleted and the pending list is kept; the next revocation retries it.

What is kept:

  • A table the user or Codex changed since Orca wrote it. Orca also stops tracking it.
  • A path that a remaining workspace at or below the removed root still uses, for example another session on the same folder.
  • An enclosing repo does not protect a nested worktree, so removing /repo/.worktrees/x still cleans up x.

Why

The issue asks that only entries Orca itself added be removed. A config file cannot tell you who wrote a table, so a record made at write time is the only reliable way to know. The alternatives each had a problem:

  • Removing every table that looks like Orca's format would also delete trust the user wrote by hand in the same format.
  • Removing tables whose path no longer exists misses folder workspaces that are removed from Orca while the folder stays on disk. It would also misfire on a volume that is temporarily unmounted.
  • Teaching the mirror to delete would change behaviour for every table it carries, not just trust Orca wrote.

The recording hook is optional on the shared trust writer, so the SSH relay, which runs the same code, does not create a ledger on remote hosts.

Linked Issue

Fixes #24697

Visual Proof

N/A: nothing visible changes in the UI. The only change is what is left in Codex's config.toml after a removal, and the tests below check those files directly.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

New tests:

  • config-toml-project-trust-removal.test.ts:
    • Adding a table and then removing it gives back the original file.
    • Removal can target specific paths in the middle of a file.
    • Tables are kept if they say untrusted, have an extra key, use a literal-string header, or use Codex's quoted "trust_level" key.
    • CRLF line endings are preserved.
  • codex-project-trust-revocation.test.ts: real files in a temporary home, written through the actual markCodexProjectTrusted and the ledger.
    • The worktree and a subfolder that was its start folder are removed from the runtime home, ~/.codex and an account home.
    • A table that existed before pre-trust is kept, and so is its account-home copy.
    • A table the user edited is kept and no longer tracked.
    • A folder shared with another remaining session is kept.
    • A nested worktree is cleaned up while its enclosing repo keeps its trust.
  • workspace-removal-codex-trust.test.ts: cleanup runs for local workspaces and for workspaces with no recorded host, folder-session ids are reduced to their real folder, and SSH hosts are skipped.
  • agent-workspace-trust.test.ts: updated for the new optional callback argument.

Commands run (macOS):

  • pnpm test src/main/codex src/main/agent-workspace-trust src/main/execution-host-workspace-trust src/main/ipc/worktrees/removal src/main/workspace-removal-codex-trust.test.ts src/relay/agent-workspace-trust: 254 files, 2780 tests passed.
  • pnpm typecheck:node and pnpm run check:code-quality:changed passed, with 0 new findings.
  • oxlint and oxfmt passed through the pre-commit hook.

Not tested: I did not run a real Orca launch-then-remove cycle, and I did not run anything on Linux, Windows or over SSH.

AI Disclosure

Written with Claude Code (Claude Opus 5.5). I reviewed the design and verification.

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

  • Existing stale entries are not cleaned up. The tables that built up before this change, such as the 95 in the report, have no ledger record, so Orca cannot tell them apart from the user's own and leaves them alone. Only trust written after this change is cleaned up.
  • SSH and runtime hosts are out of scope. On those hosts the relay writes trust to its own disk. This change only cleans up trust on this machine and skips removals on other hosts. Doing the same remotely would mean a relay-side ledger plus a new relay call, which per remote-wire-compatibility.md should come in its own PR.
  • WSL: local pre-trust never writes Codex trust for WSL launches, so there is nothing to clean up there.
  • Cross-platform: paths are compared with the existing isPathInsideOrEqual and realpath forms. A removed checkout is resolved through its parent folder, which still exists.
  • Overlap: fix(codex): edit Codex config.toml through one parser-checked writer (1/2) #23930 and fix(codex): Orca's Codex hook stays on, is recognised, and trust reaches every home (2/2) #23931 are rewriting the Codex config.toml writer. This PR touches upsertProjectTrustLevel in only one place, to report whether it created the table, so whichever lands second should be easy to rebase.
  • Performance: cleanup runs in the background after metadata removal. It reads one small JSON ledger and only opens config.toml files when a recorded path matches.

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)

🤖 Generated with Claude Code

@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.

🧰 Additional context used
📚 Code guidelines (1)
AGENTS.md — auto-discovered
📝 Walkthrough

Walkthrough

Codex trust creation now records newly created project-table paths in a ledger. When a local worktree is removed, the revocation flow removes eligible Orca-written entries from config files and stops tracking candidate paths. It preserves tables that were not written by Orca, were edited, or still belong to a remaining workspace. Account-home discovery supports locating owned Codex homes for config cleanup.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: 🟡 Moderate · up to 1bfa2

Removing a hostless remote worktree could revoke a matching local Codex trust entry. Require proof that the worktree is local before starting cleanup.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 1bfa2

The change reduces lingering trust after local workspace removal and preserves several ownership safeguards. However, overlapping removal and recreation can confuse which workspace owns a trust entry. The supported concern is bounded to local trust settings; no new remote-access or privilege-escalation path was established.

Retained concerns

  • Low · reliability · inferred: Asynchronous cleanup is keyed by reusable paths rather than workspace generations. An older removal can delete trust belonging to a recreated workspace or release newly recorded provenance. Per-file serialization does not protect the remaining-root snapshot and ledger release together. This can disrupt active trust ownership and undermine subsequent revocation, although increased attacker exposure over the previous stale-trust behavior was not established.
Security review details

Security Blast Radius

  • observed — Eligible removal can mutate multiple ledgered configuration files and every discovered owned account-home copy, not only the active account. Selection is constrained by the removed root and remaining-root protections. Non-local host removals are excluded.

Security Findings and Attack Paths

  • inferred — The supported race requires overlapping cleanup and trust creation at a reusable path. Cleanup may retain an obsolete ownership snapshot or release a recreated entry because provenance has only config-and-path identity. The inspected paths do not establish an attacker-triggerable cross-user or remote authority bypass.

Trust Boundaries and Controls

  • observed — Source-table deletion requires recorded provenance and an exact Orca-written table shape. User-modified tables survive. Account-copy removal additionally checks that neither source configuration still trusts the path and uses owned-home validation. These controls are substantive, but their checks do not form one transaction with concurrent creation.

Resilience and Maintainability Implications

  • observed — The ledger is atomically written with restrictive permissions. Pending account-copy cleanup is persisted and cleared only after processing discovered homes. Non-absence source errors and temporary home unavailability preserve work for a later invocation; the inspected recovery path depends on subsequent revocation.

Hardening Proposals

  • proposed — Bind revocation and provenance release to a workspace generation, or coordinate them with trust creation under a shared lifecycle guard. Revalidate source trust before account-copy deletion under that coordination so delayed cleanup cannot act on a newer owner.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.24% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 37 functions across 17 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: removing Codex trust that Orca wrote when a worktree is removed.
Description check ✅ Passed The description covers the required sections, explains the change and rationale, links issue #24697, gives visual-proof status, and reports tests and limitations. The full lint, typecheck, test, and b…
Linked Issues check ✅ Passed The implementation meets [#24697]. It records trust tables when Orca creates them and invokes local cleanup from worktree and workspace removal paths. Cleanup removes recorded tables only when they st…
Out of Scope Changes check ✅ Passed The ledger, trust-table helpers, removal hooks, account-home cleanup, and tests directly support [#24697]. The stated exclusions for remote-host cleanup and WSL trust do not add unrelated changes. No …
  • Fix all pre-merge checks with AI
  • 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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 338d7ab6-5116-480d-aab2-35907198aec5

📥 Commits

Reviewing files that changed from the base of the PR and between 1fc24d3 and 7ccf3af28c19800d3ca32a5246913b7d14011947.

📒 Files selected for processing (17)
  • src/main/agent-trust-presets.ts
  • src/main/agent-workspace-trust.test.ts
  • src/main/agent-workspace-trust.ts
  • src/main/codex/codex-account-home-discovery.ts
  • src/main/codex/codex-project-trust-ledger.ts
  • src/main/codex/codex-project-trust-revocation.test.ts
  • src/main/codex/codex-project-trust-revocation.ts
  • src/main/codex/config-toml-project-duplicate-repair.ts
  • src/main/codex/config-toml-project-trust-removal.test.ts
  • src/main/codex/config-toml-project-trust-removal.ts
  • src/main/codex/config-toml-project-trust.ts
  • src/main/codex/config-toml-trust.ts
  • src/main/execution-host-workspace-trust.ts
  • src/main/ipc/worktrees/removal/worktree-removal-ownership.ts
  • src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts
  • src/main/workspace-removal-codex-trust.test.ts
  • src/main/workspace-removal-codex-trust.ts

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

Comment thread src/main/agent-trust-presets.ts
Comment thread src/main/codex/codex-project-trust-ledger.ts Outdated
Comment thread src/main/codex/codex-project-trust-revocation.ts Outdated
Comment thread src/main/codex/codex-project-trust-revocation.ts Outdated

@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.

Important

The happy path is correct and well-tested, but a few error paths can strand the ledger or delete trust prematurely. All are anchored inline.

Reviewed changes

  • Trust ledger (codex-project-trust-ledger.ts): records each config file and project path only when upsertProjectTrustLevel creates the table, in codex-runtime-home/project-trust-ledger.json.
  • Revocation (codex-project-trust-revocation.ts): on local workspace removal, deletes ledgered [projects."<path>"] tables at or below the removed root from every recorded config, then the mirror copies from each owned account home — only when the table is still exactly Orca's shape and no remaining workspace at or below the root claims the path.
  • TOML removal (config-toml-project-trust-removal.ts): line-splice removal reusing readTomlTables/isOrcaWrittenTable/getTrustTableKind (newly exported), preserving CRLF and the trailing separator.
  • Removal wiring (workspace-removal-codex-trust.ts): fire-and-forget after metadata is gone, on both the runtime purge and the UI metadata purge; SSH and other hosts are skipped, and folder-session ids are reduced to their real folder.
  • Discovery refactor (codex-account-home-discovery.ts): exposes getOwnedCodexAccountHomePaths() for the account-home sweep.
Technical details
# Review scope

Full 17-file diff at `7ccf3af`. Ran the focused new suites (21 tests, all pass), the
changed-code-quality gate (0 findings), and traced the real callers
(`removeWorktreeMetadataAndTransientState`, `removeWorktreeMetadataAndHistory`,
`getLocalCodexTrustConfigFiles`, the config mirror's `untrusted` handling). No critical or
security issue found; the findings below are durability/error-path concerns only.

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

Comment thread src/main/agent-trust-presets.ts
Comment thread src/main/codex/codex-project-trust-ledger.ts Outdated
Comment thread src/main/codex/codex-project-trust-revocation.ts Outdated
Comment thread src/main/codex/codex-project-trust-revocation.ts
Comment thread src/main/codex/codex-project-trust-revocation.ts Outdated

@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 new issues found.

Reviewed changes

de1b3f2 ("keep trust cleanup recoverable when a step fails") hardens the Codex trust cleanup against partial failures and addresses every finding from the prior review:

  • Ledger durability (codex-project-trust-ledger.ts): writes now go through writeFileAtomically; the ledger gains pendingMirrorCleanup, and the new releaseCodexProjectTrust stops tracking released paths and queues their mirror cleanup in a single atomic write.
  • Unreadable-source safety (codex-project-trust-revocation.ts): readConfigOrEmpty now treats only definitive absence as empty and rethrows otherwise, and the new projectTrustTableTrusts counts an explicit untrusted source as not trusting the path.
  • Account-home sweep (codex-account-home-discovery.ts): getOwnedCodexAccountHomePaths({ strict: true }) surfaces temporary home-unavailability, so a failed sweep preserves the pending record for the next revocation instead of dropping it.
  • Launch resilience (agent-trust-presets.ts): a throwing onTableCreated can no longer abort the remaining config writes.
  • Tests (codex-project-trust-revocation.test.ts): new cases cover an unreadable source keeping the mirror copy, a retry after an unreachable account root, and a throwing ledger callback still writing trust everywhere.

Verification: the three focused suites pass (16 tests) and check:code-quality:changed reports 0 findings across the 17 changed files.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Waynting and others added 2 commits October 3, 2026 20:16
…oved

Orca pre-trusts each folder it starts Codex in by writing a
[projects."<path>"] table to config.toml, and the config mirror copies
those tables into every managed account home. Nothing ever removed
them, so trust outlived the worktree and covered whatever later
appeared at a reused path.

Record in a ledger each table Orca's pre-trust created (never one that
already existed). When a local workspace is removed, delete the
ledgered tables at or below its root that still hold exactly what Orca
wrote, then their mirrored copies in account homes once no source
trusts the path. Tables a user edited, and folders another remaining
workspace still uses, are kept.

Fixes stablyai#24697

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-ups for stablyai#24697:
- A ledger write that throws no longer stops trust reaching the
  remaining config files.
- The ledger is written atomically, so a torn write cannot erase it.
- Released paths are queued in the ledger before account homes are
  touched, and the queue is retried on the next revocation, so an
  unreadable accounts root no longer strands mirror copies.
- Only a definitively absent config reads as empty; an unreadable one
  aborts instead of letting mirror copies be deleted.
- A source that says `untrusted` no longer shields its mirror copies,
  matching how the config mirror reads it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Waynting
Waynting force-pushed the fix/codex-worktree-trust-cleanup branch from de1b3f2 to 1bfa22a Compare October 3, 2026 12:17

@coderabbitai coderabbitai 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 74dcd532-48ad-45a7-b693-f23245e6cb2c
📥 Commits

Reviewing files that changed from the base of the PR and between de1b3f21b92242b004c79ae9897796fe2aae35c9 and 1bfa22a.

📒 Files selected for processing (2)
  • src/main/execution-host-workspace-trust.ts
  • src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts

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

Comment thread src/main/runtime/orca-runtime-resolve-worktree-removal-target.ts

This branch has not been deployed

No deployments
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 pre-trust entries for worktrees stay in the managed account config.toml after worktree rm

1 participant