Skip to content

feat(codex): add always plugin approval mode#97123

Merged
kevinslin merged 3 commits into
mainfrom
codex/codex-destructive-actions-always
Jun 27, 2026
Merged

feat(codex): add always plugin approval mode#97123
kevinslin merged 3 commits into
mainfrom
codex/codex-destructive-actions-always

Conversation

@kevinslin

@kevinslin kevinslin commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Codex plugin app configuration needed a mode stricter than auto: allow_destructive_actions: "always" should keep destructive/write plugin actions available while requiring user elicitation every time, including after a prior approval in the same session.

Why This Change Was Made

This adds "always" as a supported Codex destructive-action policy across the manifest schema, config normalization, session binding, migration contracts, command docs, and native plugin docs. For Codex app-server threads, "always" still keeps Codex read-only tools on default_tools_approval_mode: "auto", but clears only persisted per-tool approval_mode leaves through Codex config/value/write before exposing write apps so prior Codex session approval cannot bypass OpenClaw plugin approval.

The latest fix also passes the thread cwd into Codex config reads, treats config/value/write responses with status: "okOverridden" as cleanup failures, and re-reads the effective cwd-scoped config after cleanup. If any durable per-tool approval override still wins from another layer, OpenClaw omits the app instead of exposing a false every-write approval guarantee.

Checked upstream Codex behavior in sibling source: ../codex/codex-rs/config/src/mcp_types.rs, ../codex/codex-rs/core/src/connectors.rs, ../codex/codex-rs/core/src/mcp_tool_call.rs, ../codex/codex-rs/app-server-protocol/src/protocol/v2/config.rs, ../codex/codex-rs/app-server/src/config_manager_service.rs, ../codex/codex-rs/config/src/merge.rs, and ../codex/codex-rs/utils/json-to-toml/src/lib.rs.

User Impact

Users can set allow_destructive_actions: "always" for Codex apps to require approval for every destructive plugin tool call while leaving read-only plugin tools usable without prompts. Existing true, false, and "auto" behavior remains unchanged.

Evidence

  • node scripts/run-vitest.mjs extensions/codex/src/app-server/config.test.ts extensions/codex/src/app-server/plugin-thread-config.test.ts extensions/codex/src/app-server/elicitation-bridge.test.ts extensions/codex/src/app-server/session-binding.test.ts extensions/codex/doctor-contract-api.test.ts extensions/codex/src/app-server/request.test.ts extensions/codex/src/migration/provider.test.ts passed: 7 files, 244 tests.
  • git diff --check passed.
  • pnpm format:docs:check passed.
  • Fresh autoreview completed with no accepted/actionable findings after fixes.
  • CI fix commit c06f61d: pnpm tsgo:prod passed, node scripts/run-vitest.mjs extensions/codex/src/app-server/elicitation-bridge.test.ts passed: 1 file, 49 tests, and git diff --check passed.
  • Layered override fix commit 9fad4a0: node scripts/run-vitest.mjs extensions/codex/src/app-server/plugin-thread-config.test.ts passed: 1 file, 24 tests; pnpm tsgo:prod passed; pnpm exec oxfmt --write --threads=1 extensions/codex/src/app-server/plugin-thread-config.ts extensions/codex/src/app-server/plugin-thread-config.test.ts extensions/codex/src/app-server/attempt-startup.ts completed; git diff --check passed; fresh autoreview completed with no accepted/actionable findings.
  • Live dev-profile Slack proof captured the actual approval buttons in Slack. Inspectable screenshot: https://ik.imagekit.io/fpjzhqpv1/openclaw/pr-97123/openclaw-pr-97123-slack-approval-buttons-redo2_CVNHPhrfW.png. The screenshot shows approval ID plugin:d500955f-e007-4fa8-a1fe-911e0e7ebe06 with Allow Once, Allow Always, and Deny buttons.
  • After clicking Allow Once, Slack showed Plugin approval: Allowed once, and plugin.approval.waitDecision returned decision: "allow-once" for the same approval ID in .mem/main/proofs/demo-49-openclaw-codex-dev-slack-plugin-buttons/raw/plugin-approval-wait-decision-redo2.json. Inspectable resolved-state screenshot: https://ik.imagekit.io/fpjzhqpv1/openclaw/pr-97123/openclaw-pr-97123-slack-approval-resolved-redo2_909x5V0EC.png.
  • uvx showboat verify .mem/main/proofs/demo-49-openclaw-codex-dev-slack-plugin-buttons/raw/showboat-summary.md passed. This redo uses a controlled live plugin.approval.request to prove Slack button rendering and resolution; the earlier Google Calendar request had already created the event without presenting a fresh Slack approval card.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime extensions: codex size: L maintainer Maintainer-authored PR labels Jun 26, 2026
@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 27, 2026, 4:13 AM ET / 08:13 UTC.

Summary
The PR adds a new Codex plugin destructive-action policy value, "always", across config schema, app-server thread setup, approval elicitation handling, session binding, migration preservation, docs, and tests.

PR surface: Source +143, Tests +654, Docs +11. Total +808 across 19 files.

Reproducibility: not applicable. as a feature PR: current main and v2026.6.10 support only boolean or "auto" for this setting. The validation need is live behavior proof for the new mode, not a current-main bug reproduction.

Review metrics: 2 noteworthy metrics.

  • Config policy surface: 1 value added; 2 manifest schema sites changed. The PR adds a persisted Codex plugin destructive-action mode, so config, docs, migration, and upgrade behavior need maintainer-visible review.
  • Sandbox direct methods: 2 methods added. config/read and config/value/write become sandbox-allowed app-server control-plane methods, which matters for security-boundary review.

Stored data model
Persistent data-model change detected: migration/backfill/repair: extensions/codex/src/migration/plan.ts, migration/backfill/repair: extensions/codex/src/migration/provider.test.ts, serialized state: extensions/codex/src/app-server/session-binding.test.ts, unknown-data-model-change: extensions/codex/src/migration/plan.ts, unknown-data-model-change: extensions/codex/src/migration/provider.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🦪 silver shellfish
Patch quality: 🧂 unranked krab
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Remove or tightly scope sandboxed Codex config read/write access.
  • [P1] Add redacted live Codex app-server proof showing a second prompt after Allow Once.
  • [P1] Show either durable per-tool approval cleanup or intended fail-closed app omission when another config layer still overrides it.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The inspected screenshots show Slack approval buttons and an allow-once resolution, but not a real Codex allow_destructive_actions: "always" thread proving a second prompt or override cleanup/fail-closed behavior; the contributor should add redacted logs, terminal/live output, or a recording and update the PR body for a fresh review.

Mantis proof suggestion
A Slack desktop smoke would materially prove the visible one-shot approval buttons and repeated-prompt behavior for the configured Codex mode. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis slack desktop smoke: verify Codex plugin allow_destructive_actions "always" shows only one-shot/deny approval for a destructive app action, then prompts again on a second write action.

Risk before merge

  • [P1] The PR adds a new persisted Codex plugin policy value and can intentionally omit configured plugin apps when durable approval overrides cannot be cleared, so upgrade behavior needs explicit maintainer acceptance.
  • [P1] config/read and config/value/write become allowed direct app-server methods in sandboxed sessions, broadening a security boundary beyond the narrow startup cleanup need.
  • [P1] The screenshots prove controlled Slack approval rendering and one resolved decision, but not a real Codex always thread with a second destructive prompt or durable override cleanup/fail-closed behavior.

Maintainer options:

  1. Scope the config cleanup path (recommended)
    Before merge, keep broad config/read and config/value/write out of the sandbox direct-method allow-list or route cleanup through a private parameter-scoped startup path that can only clear per-tool approval overrides for the selected app.
  2. Require real always-mode proof
    Ask for redacted live Codex app-server proof showing one-shot-only approval, a second prompt on the next destructive action, and cleanup or fail-closed behavior when existing overrides are present.
  3. Accept the boundary intentionally
    Maintainers may decide the broader config access and fail-closed app omission are acceptable, but that should be an explicit human product/security decision before merge.

Next step before merge

  • [P1] The protected maintainer label, security-boundary/product decision, and insufficient real behavior proof make this a human-review item rather than an automated repair lane.

Security
Needs attention: No supply-chain issue was found, but the diff broadens sandboxed Codex config read/write access and needs a narrower fix or explicit maintainer security acceptance.

Review findings

  • [P1] Keep config access out of the broad sandbox allow-list — extensions/codex/src/app-server/sandbox-guard.ts:22-23
Review details

Best possible solution:

Land only after sandboxed Codex config access is removed or tightly scoped, maintainers explicitly accept the remaining compatibility/security tradeoff, and redacted real Codex proof shows repeated one-shot approval plus cleanup or fail-closed behavior.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a feature PR: current main and v2026.6.10 support only boolean or "auto" for this setting. The validation need is live behavior proof for the new mode, not a current-main bug reproduction.

Is this the best way to solve the issue?

No: the feature direction is plausible, and the cleanup/fail-closed approach matches upstream Codex constraints, but the generic sandbox allow-list expansion is broader than the narrow startup cleanup path and the real always-mode path is still not proven.

Full review comments:

  • [P1] Keep config access out of the broad sandbox allow-list — extensions/codex/src/app-server/sandbox-guard.ts:22-23
    Adding config/read and config/value/write as allowed-control-plane lets sandboxed direct app-server callers read or mutate Codex user config through the generic guarded helper. The always cleanup path is wired through the startup client directly, so keep these methods blocked here or replace this with a narrower cleanup-only path.
    Confidence: 0.84

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against fbfadbd806e1.

Label changes

Label justifications:

  • P2: This is a normal-priority Codex plugin configuration feature with bounded but meaningful compatibility and security-boundary review needs.
  • merge-risk: 🚨 compatibility: The PR adds a new persisted config value and can omit configured plugin apps when existing Codex approval overrides cannot be cleared.
  • merge-risk: 🚨 security-boundary: The PR allows direct Codex config read/write requests in sandboxed sessions and changes destructive plugin approval enforcement.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🦪 silver shellfish and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The inspected screenshots show Slack approval buttons and an allow-once resolution, but not a real Codex allow_destructive_actions: "always" thread proving a second prompt or override cleanup/fail-closed behavior; the contributor should add redacted logs, terminal/live output, or a recording and update the PR body for a fresh review.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The inspected screenshots show Slack approval buttons and an allow-once resolution, but not a real Codex allow_destructive_actions: "always" thread proving a second prompt or override cleanup/fail-closed behavior; the contributor should add redacted logs, terminal/live output, or a recording and update the PR body for a fresh review.
Evidence reviewed

PR surface:

Source +143, Tests +654, Docs +11. Total +808 across 19 files.

View PR surface stats
Area Files Added Removed Net
Source 10 175 32 +143
Tests 7 655 1 +654
Docs 2 19 8 +11
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 19 849 41 +808

Security concerns:

  • [medium] Broad Codex config access in sandboxed sessions — extensions/codex/src/app-server/sandbox-guard.ts:23
    config/read and config/value/write become allowed for sandboxed direct app-server requests, turning a narrow approval-cleanup need into generic Codex user-config access through the guarded helper.
    Confidence: 0.84

What I checked:

Likely related people:

  • kevinslin: Recent merged history on native Codex plugin apps, auto plugin approvals, remote app-server plugins, and the same thread config/elicitation/config surfaces overlaps this PR's central behavior. (role: recent feature owner; confidence: high; commits: a1ac559ed7e6, e82d19fb06b5, bc5081c58730; files: extensions/codex/src/app-server/plugin-thread-config.ts, extensions/codex/src/app-server/elicitation-bridge.ts, extensions/codex/src/app-server/config.ts)
  • joshavant: Prior merged work introduced and maintained the Codex app-server native execution and sandbox guard boundary that this PR expands through direct config methods. (role: adjacent sandbox/security contributor; confidence: medium; commits: ba06376c7955, e0405ecc9bd6; files: extensions/codex/src/app-server/sandbox-guard.ts)
  • steipete: Recent history includes Codex plugin app configuration docs and large extension/docs refactors overlapping the user-visible docs touched by this PR. (role: adjacent docs/refactor contributor; confidence: medium; commits: d99268ae514a, 729712d19467, 6868cde4d45f; files: docs/plugins/codex-native-plugins.md, docs/gateway/configuration-reference.md, extensions/codex/src/app-server/elicitation-bridge.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edabe7ceaf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread extensions/codex/src/app-server/plugin-thread-config.ts Outdated
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 26, 2026
@kevinslin

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated proof is now inspectable from the PR body instead of local-only .mem paths.

Slack approval buttons screenshot:

Slack approval buttons

Resolved state screenshot:

Slack approval resolved

The screenshots show approval ID plugin:d500955f-e007-4fa8-a1fe-911e0e7ebe06; after clicking Allow Once, plugin.approval.waitDecision returned decision: "allow-once" for the same ID.

Maintainer acceptance for the security-boundary items called out in the review: the durable per-tool approval cleanup and the narrow sandbox allowance for config/read plus config/value/write are intentional for this mode. The implementation fails closed when cleanup cannot prove that lower-layer durable approval overrides are gone.

@clawsweeper

clawsweeper Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 27, 2026
@kevinslin

Copy link
Copy Markdown
Contributor Author

Land-ready verification for PR #97123.

  • Prepared head SHA: 9fad4a09573d078143a5996922ac562f690dc08a.
  • Repo wrapper: OPENCLAW_TESTBOX=1 scripts/pr prepare-run 97123 passed with gates_mode=hosted_exact_head; remote PR head already matched the local prep head.
  • Hosted checks for the exact head are green, including check-lint, build-artifacts, check-prod-types, check-test-types, security guards, and the compact node shards.
  • Local wrapper retry also passed pnpm build and pnpm check after extending the oxlint shard timeout. Broad local pnpm test is not used as merge evidence here because it fails on unrelated baseline areas; representative failures reproduce on origin/main via the wrapper temp branch (src/security/install-policy.test.ts forked pid ENOENT and src/plugin-sdk/provider-catalog-shared.test.ts native streaming usage assertions).
  • Focused PR proof remains the Codex approval tests plus live Slack approval-button screenshot proof linked in the PR body.

Known proof gap: local full-suite baseline is currently noisy outside the changed Codex approval surface, so the merge evidence is the repo wrapper's hosted exact-head gate plus focused PR proof.

@kevinslin
kevinslin force-pushed the codex/codex-destructive-actions-always branch from 9fad4a0 to 31d4ea6 Compare June 27, 2026 08:08
@kevinslin
kevinslin merged commit c5d34c8 into main Jun 27, 2026
87 checks passed
@kevinslin
kevinslin deleted the codex/codex-destructive-actions-always branch June 27, 2026 08:19
@kevinslin

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 28, 2026
* feat(codex): add always plugin approval mode

* fix(codex): normalize plugin approval decisions

* fix(codex): fail closed on layered approval overrides
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
* feat(codex): add always plugin approval mode

* fix(codex): normalize plugin approval decisions

* fix(codex): fail closed on layered approval overrides
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
* feat(codex): add always plugin approval mode

* fix(codex): normalize plugin approval decisions

* fix(codex): fail closed on layered approval overrides
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
* feat(codex): add always plugin approval mode

* fix(codex): normalize plugin approval decisions

* fix(codex): fail closed on layered approval overrides
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation extensions: codex gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant