Skip to content

fix(codex): enforce native tool policy#82496

Merged
joshavant merged 3 commits into
mainfrom
fix/codex-native-tool-policy
May 16, 2026
Merged

fix(codex): enforce native tool policy#82496
joshavant merged 3 commits into
mainfrom
fix/codex-native-tool-policy

Conversation

@joshavant

Copy link
Copy Markdown
Contributor

Summary

  • Problem: Codex app-server native shell/file operations could bypass OpenClaw before_tool_call policy when Codex ran in implicit yolo mode.
  • Why it matters: plugin policy is expected to cover tool execution, including Codex-native tool surfaces.
  • What changed: OpenClaw now injects a trusted Codex native hook relay, promotes implicit Codex yolo to untrusted only when allowed, and routes Codex approval requests through OpenClaw policy before prompting.
  • What did NOT change (scope boundary): explicit Codex app-server mode/policy settings and requirements-constrained never approval policy remain respected.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • 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

Real behavior proof (required for external PRs)

  • Behavior addressed: Codex-native shell request is intercepted by OpenClaw before_tool_call policy and denied before writing the blocked target file.
  • Real environment tested: Crabbox AWS on-demand Linux host, Codex CLI 0.130.0, OpenAI gpt-5.5, real OpenClaw agent run with a local test plugin registered for before_tool_call.
  • Exact steps or command run after this patch: node scripts/crabbox-wrapper.mjs run --provider aws --market on-demand --idle-timeout 90m --ttl 180m --timing-json --env-from-profile /private/tmp/openclaw-82372-live-env.sh --allow-env OPENAI_API_KEY,OPENAI_BASE_URL --script .crabbox/tmp/oc82372-e2e.sh
  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output): Crabbox run run_90168d2aaf64; output included agent_status=0, hook_log_count=1, target_exists=0, target_size=0, and FIXED: Codex native shell request was intercepted by OpenClaw before_tool_call policy and target file was not created.
  • Observed result after fix: the OpenClaw hook ran once and the requested /tmp/oc82372-crabbox-private_key.txt target was not created.
  • What was not tested: full GitHub CI was not complete at PR creation time.
  • Before evidence (optional but encouraged): current main was reproduced on Crabbox run run_a4bce79c6487; the plugin hook was visible but hook_log_count=0 and target_exists=1.

Root Cause (if applicable)

  • Root cause: the Codex app-server harness did not enable an OpenClaw-owned native hook relay for Codex-native tool execution, so OpenClaw policy only covered OpenClaw dynamic tools and later approval prompts.
  • Missing detection / guardrail: no live regression proof covered Codex-native shell execution under a plugin before_tool_call policy.
  • Contributing context (if known): Codex app-server hook trust uses session-flags source paths and current-hook hashes, so the relay config has to match Codex's trusted hook identity.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/codex/src/app-server/native-hook-relay.test.ts, extensions/codex/src/app-server/run-attempt.test.ts, extensions/codex/src/app-server/approval-bridge.test.ts, extensions/codex/index.test.ts
  • Scenario the test should lock in: public Codex app-server attempts enable native relay config, app-server approval requests run OpenClaw policy first, unsafe rewrites fail closed, and implicit yolo promotion respects Codex requirements.
  • Why this is the smallest reliable guardrail: these tests cover the new seam boundaries without running live provider flows in unit CI.
  • Existing test that already covers this (if any): none for the live Codex-native tool bypass.

User-visible / Behavior Changes

Codex plugin users with OpenClaw tool policy hooks now get the same deny/approval behavior for Codex-native app-server tools that they expect for OpenClaw-owned dynamic tools. Explicit Codex app-server policy configuration remains honored.

Diagram (if applicable)

Before:
Codex-native shell -> Codex app-server -> executes without OpenClaw before_tool_call

After:
Codex-native shell -> Codex native hook/app-server approval -> OpenClaw before_tool_call -> allow/deny

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? Yes
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: Codex-native command approvals now consult OpenClaw policy before proceeding; policy rewrites that cannot be applied to Codex-native execution fail closed.

Repro + Verification

Environment

  • OS: macOS local focused tests; Linux Crabbox AWS for live E2E
  • Runtime/container: Node 22 on Crabbox; repo pnpm workspace
  • Model/provider: OpenAI gpt-5.5
  • Integration/channel (if any): Codex plugin app-server harness
  • Relevant config (redacted): local test plugin registering before_tool_call; model credentials forwarded via private Crabbox env profile

Steps

  1. Register a test plugin that logs and blocks before_tool_call events containing the private-key target path.
  2. Run a Codex app-server-backed OpenClaw agent and instruct it to use native shell to write /tmp/oc82372-crabbox-private_key.txt.
  3. Verify the hook log and target file state.

Expected

  • OpenClaw policy hook runs and denies the Codex-native shell request.
  • Target file is not created.

Actual

  • hook_log_count=1
  • target_exists=0
  • target_size=0

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: focused Vitest coverage, TypeScript lanes, plugin SDK API baseline, Codex review, and live Crabbox E2E.
  • Edge cases checked: Codex requirements disallowing untrusted, explicit yolo config, plugin approval-required outcomes, policy param rewrites, raw command vs parsed display command.
  • What you did not verify: full GitHub CI at PR creation time.

Compatibility / Migration

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

Risks and Mitigations

  • Risk: Codex hook trust identity changes in future Codex versions.
    • Mitigation: relay config is covered by focused tests and live proof against Codex CLI 0.130.0.
  • Risk: app-server approvals cannot safely apply OpenClaw param rewrites to Codex-native execution.
    • Mitigation: this path fails closed when policy rewrites params.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation agents Agent runtime and tooling extensions: codex size: L maintainer Maintainer-authored PR labels May 16, 2026
@clawsweeper

clawsweeper Bot commented May 16, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge.

Summary
The PR enables Codex app-server native hook relay trust/config, promotes implicit yolo policy when OpenClaw tool policy exists, routes Codex approval requests through before_tool_call, updates SDK exports, adds tests, and records a changelog fix.

Reproducibility: yes. The PR body gives a concrete Crabbox current-main before path and after-fix live path for Linux, and source inspection shows the current-main Codex native relay lacks the new trusted hook state and approval-policy bridge.

Real behavior proof
Sufficient (live_output): The PR body includes after-fix Linux Crabbox live output with a real Codex app-server run, hook count, target file state, and before-run contrast.

Next step before merge
The PR is protected by the maintainer label and has a security-sensitive cross-platform correctness finding that should be handled by the PR author or a maintainer, not by a cleanup close.

Security
Needs attention: The patch hardens native policy enforcement, but the missing Windows trust key leaves a concrete cross-platform security gap.

Review findings

  • [P2] Add Windows session hook state keys — extensions/codex/src/app-server/native-hook-relay.ts:31-34
Review details

Best possible solution:

Keep the security fix direction, add cross-platform Codex session-flags hook-state key coverage or derive the key from Codex-compatible path logic, then rerun focused tests and live proof before maintainer merge.

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

Yes. The PR body gives a concrete Crabbox current-main before path and after-fix live path for Linux, and source inspection shows the current-main Codex native relay lacks the new trusted hook state and approval-policy bridge.

Is this the best way to solve the issue?

No. The approach is the right owner boundary, but it is not complete until the trusted session hook keys work on Windows as well as Unix-like hosts.

Full review comments:

  • [P2] Add Windows session hook state keys — extensions/codex/src/app-server/native-hook-relay.ts:31-34
    hooks.state only pre-trusts /<session-flags>/config.toml and <session-flags>/config.toml. Codex builds the hook-state key from the displayed session-flags config path, which resolves against C:\ on Windows, and non-managed hooks are only active when that key is trusted; on Windows these relay hooks remain untrusted and the native policy bypass can persist. (raw.githubusercontent.com)
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.86

Security concerns:

  • [medium] Windows native hooks remain untrusted — extensions/codex/src/app-server/native-hook-relay.ts:31
    The trusted hooks.state keys do not include Codex's Windows session-flags source path form, so Windows Codex app-server runs can skip the relay handlers that are meant to enforce before_tool_call policy.
    Confidence: 0.86

What I checked:

  • Protected label: The provided GitHub context lists the maintainer label, which repository policy treats as protected and keeps open for explicit maintainer handling.
  • Current main native relay state: Current main builds Codex native hook relay config with features.hooks and hook event entries, but without trusted hooks.state entries. (extensions/codex/src/app-server/native-hook-relay.ts:23, 23f73b3ecfd9)
  • PR head native relay change: The PR head adds CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS and emits trusted hooks.state entries, but the path list contains only Unix-style /<session-flags>/config.toml and relative <session-flags>/config.toml keys. (extensions/codex/src/app-server/native-hook-relay.ts:31, e3633a3e9ad5)
  • PR head approval policy bridge: The PR head promotes implicit yolo to untrusted when OpenClaw tool policy exists and calls runBeforeToolCallHook before Codex app-server approval prompting. (extensions/codex/src/app-server/run-attempt.ts:510, e3633a3e9ad5)
  • Dependency contract check: OpenAI Codex hook discovery builds hook-state keys from the displayed config source path plus event label/index, resolves session-flags config paths against C:\ on Windows and / elsewhere, and only activates non-managed command hooks when enabled and trusted. (raw.githubusercontent.com)
  • Real behavior proof in PR body: The PR body reports Linux Crabbox before/after evidence: before run run_a4bce79c6487 had hook_log_count=0 and target_exists=1, while after run run_90168d2aaf64 had hook_log_count=1, target_exists=0, and target_size=0. (e3633a3e9ad5)

Likely related people:

  • @vincentkoc: Current-main blame and recent log entries for the Codex app-server/native relay files point to recent work in this area, including current lines in the relay and approval bridge surfaces. (role: recent area contributor; confidence: medium; commits: 202dd7590d1c, 33685e14748b; files: extensions/codex/src/app-server/native-hook-relay.ts, extensions/codex/src/app-server/run-attempt.ts, extensions/codex/src/app-server/approval-bridge.ts)
  • @joshavant: Prior merged history includes before_tool_call async requireApproval work, which is directly involved in this PR's approval-mode behavior; the PR author also appears in recent Codex app-server fixes. (role: adjacent hook-policy contributor; confidence: medium; commits: 6ade9c474cf1; files: src/agents/pi-tools.before-tool-call.ts, extensions/codex/src/app-server/approval-bridge.ts)
  • Peter Steinberger: The sampled shortlog shows the largest share of commits across the Codex app-server and hook/SDK surfaces, including release/package SDK work around these paths. (role: historical app-server and SDK area contributor; confidence: medium; commits: f066dd2f31c2, 4862d349257a; files: extensions/codex/src/app-server, src/plugin-sdk/agent-harness-runtime.ts)

Remaining risk / open question:

  • Windows Codex app-server native hook enforcement is not covered by the PR proof and appears incomplete because the trusted session hook key omits the Windows source path shape.
  • The fix depends on Codex hook trust-key internals, so cross-platform tests should lock the generated key contract.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 23f73b3ecfd9.

@joshavant joshavant force-pushed the fix/codex-native-tool-policy branch from 0224add to 53cfb7e Compare May 16, 2026 07:42
@joshavant joshavant force-pushed the fix/codex-native-tool-policy branch from 53cfb7e to e3633a3 Compare May 16, 2026 07:44
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 16, 2026
@joshavant joshavant merged commit e57b137 into main May 16, 2026
114 of 117 checks passed
@joshavant joshavant deleted the fix/codex-native-tool-policy branch May 16, 2026 08:02
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 20, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 25, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
qiaokuan1992 pushed a commit to qiaokuan1992/openclaw that referenced this pull request Jun 2, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
* fix(codex): enforce native tool policy

* docs: add changelog for codex native policy fix

* fix(codex): satisfy native hook relay lint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation extensions: codex maintainer Maintainer-authored PR proof: sufficient ClawSweeper judged the real behavior proof convincing. size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Codex harness bypass persists after #82078 — native-hook-relay registration silently skipped, hooks block never sent in thread/start

1 participant