Skip to content

fix(secrets): allow root-owned exec providers#809

Open
artemgetmann wants to merge 1 commit into
mainfrom
codex/secret-provider-system-command-20260528
Open

fix(secrets): allow root-owned exec providers#809
artemgetmann wants to merge 1 commit into
mainfrom
codex/secret-provider-system-command-20260528

Conversation

@artemgetmann
Copy link
Copy Markdown
Owner

Review Fast Path

  • User path fixed: Jarvis/Telegram config reload can use a configured exec secret provider backed by macOS system tools like /usr/bin/security.
  • Proof: src/secrets/resolve.test.ts now passes through a root-owned /bin/sh exec provider when it is not group/world writable; requested focused Vitest targets pass.
  • Shared-state footgun removed: stale runtime state no longer masks freshly written redacted config because provider validation no longer rejects root-owned system commands by default.
  • Still hurts: no live gateway reload was run in this lane; proof is focused unit/runtime regression only.

Summary

  • Problem: POSIX secret provider path validation rejected /usr/bin/security because it is root-owned instead of owned by uid 501.
  • Why it matters: macOS keychain-backed Jarvis and Telegram secret providers could be written correctly but fail runtime reload, leaving stale config active.
  • What changed: secure path validation now allows current-user-owned or root-owned POSIX paths after existing group/world writable checks pass.
  • What did NOT change (scope boundary): non-root foreign-owned paths remain rejected, group/world writable paths remain rejected, symlink/trustedDirs behavior remains unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #

User-visible / Behavior Changes

Configured exec secret providers may now use root-owned POSIX system commands such as /usr/bin/security when the command is not group/world writable.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No raw secret handling changed; provider resolution can now invoke trusted root-owned system commands already configured by the user.
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) Yes
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation: POSIX exec provider validation now trusts root ownership as well as current-user ownership, but only after rejecting group/world writable paths. Non-root foreign-owned provider paths remain rejected.

Repro + Verification

Environment

  • OS: macOS local worker lane
  • Runtime/container: local Node/Vitest via pnpm
  • Model/provider: N/A
  • Integration/channel (if any): secret provider config used by Jarvis/Telegram runtime reload
  • Relevant config (redacted): exec provider command path shape only; no secrets printed

Steps

  1. Configure an exec secret provider using a root-owned POSIX system command such as /usr/bin/security.
  2. Reload runtime secrets/config.
  3. Resolve refs that depend on the exec provider.

Expected

  • Root-owned, non-group/world-writable system commands pass provider path validation.
  • Group/world writable provider paths still fail.
  • Non-root foreign-owned provider paths still fail.

Actual

  • Before: validation failed with must be owned by the current user for root-owned system commands.
  • After: validation accepts root-owned secure system commands and the focused regression passes.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • pnpm vitest run --config vitest.unit.config.ts --pool=forks src/secrets/resolve.test.ts --maxWorkers 1 passed: 1 file, 18 tests.
    • pnpm vitest run --config vitest.unit.config.ts --pool=forks src/secrets/runtime.test.ts -t "Jarvis|resolves Jarvis" --maxWorkers 1 passed: 1 file, 1 test, 60 skipped.
    • git diff --check passed.
  • Edge cases checked: root-owned system command test only registers when /bin/sh is root-owned and not group/world writable; existing rejection tests for symlink/trustedDirs/provider protocol still pass.
  • What you did not verify: live gateway reload with the actual Jarvis keychain provider and Telegram bot verification.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert commit feb22802e706040c3c7249c21801450f8728f4de.
  • Files/config to restore: src/secrets/resolve.ts, src/secrets/resolve.test.ts.
  • Known bad symptoms reviewers should watch for: exec providers using root-owned system tools fail again with must be owned by the current user; overly permissive command paths should still fail with permissions are too open.

Risks and Mitigations

  • Risk: trusting root-owned paths could be too broad if write-bit checks regress later.
    • Mitigation: root-owned acceptance is placed after existing group/world writable rejection, and the regression test covers only a non-writable root-owned command.

AI Assistance

  • AI-assisted
  • Testing degree: targeted

- What: allow POSIX root-owned secure paths after existing group/world write checks pass.
- Why: macOS system tools like /usr/bin/security are root-owned and should be usable as configured exec secret providers.
- Risk: non-root foreign-owned provider paths remain rejected; group/world writable paths remain rejected.
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