Support MCP hooks in the Codex harness#71707
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Greptile SummaryThis PR bumps the minimum required Codex app-server version from Confidence Score: 5/5Safe to merge — the version gate logic is correct, test coverage is thorough, and documentation is consistent. The No files require special attention. Reviews (1): Last reviewed commit: "codex harness mcp hook parity" | Re-trigger Greptile |
76cb880 to
8be0a25
Compare
|
Addressed the build-metadata edge in 8be0a253c4. Same-base build-suffixed versions now fail the stable 0.124.0 floor, with tests for 0.124.0+alpha.2 rejection and 0.125.0+custom acceptance. |
8be0a25 to
830aa83
Compare
830aa83 to
4edf968
Compare
|
Follow-up after moving the Codex floor to 0.125.0: the runtime gate, docs, and Codex live-smoke package pin now all point at 0.125.0. I also addressed the payload-size concern from the security review by adding per-string and aggregate string budgets to native hook relay JSON validation. The other point about forwarding native tool results to plugin hooks is intentional for parity: OpenClaw |
|
I also checked a set of real third-party plugins against the MCP hook question. The useful direct analogue is Knostic Shield: its L3 path registers Most of the other sampled plugins are not native MCP hook consumers. WeCom uses |
1e21826 to
d1aa22f
Compare
|
Addressed the remaining Aisle relay DoS finding too. Native hook JSON validation now counts object key lengths against the relay string budget, and the PermissionRequest fallback key no longer joins every tool-input key into an unbounded string. The new test covers a large object-key payload on a native MCP PermissionRequest. |
|
On the Aisle PermissionRequest fail-open note: I checked Codex core before changing behavior. Codex So the relay intentionally returns a no-op when OpenClaw chooses to defer or approval is unavailable. That preserves the v1 contract of allow, deny, or defer to Codex's own approval path. I updated the relay comments/log wording to make this explicit. The object-key DoS finding was a real hardening issue and is fixed in the current head. |
|
Current head addresses the two Aisle hardening findings that were reported against earlier commits.
I added regression coverage for both cases in |
bf08b5b to
577ec1e
Compare
577ec1e to
b1eab67
Compare
|
Codex maintainer pass pushed a rebased fixup on top of this PR. What changed:
Local verification:
|
b1eab67 to
fd83a7b
Compare
fd83a7b to
c7b4402
Compare
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 DoS via unbounded key sorting/hashing of attacker-controlled toolInput in native hook relay permission requests
DescriptionThe native hook relay builds a permission-approval deduplication key by fingerprinting
Vulnerable code (hot path for for (const key of Object.keys(toolInput).toSorted()) {
if (processed >= MAX_PERMISSION_FALLBACK_KEYS) break;
...
}
for (const key of Object.keys(value).toSorted()) {
updateJsonHash(hash, value[key]);
}Impact: CPU and memory exhaustion (algorithmic complexity) by sending JSON payloads with very large numbers of object keys / nested objects. RecommendationAvoid sorting/enumerating all keys of attacker-controlled objects. Recommended changes:
function permissionRequestToolInputKeyFingerprint(toolInput: Record<string, unknown>): string {
const keys: string[] = [];
for (const key in toolInput) {
if (!Object.prototype.hasOwnProperty.call(toolInput, key)) continue;
keys.push(key);
if (keys.length >= MAX_PERMISSION_FALLBACK_KEYS) break;
}
keys.sort();
// then apply MAX_PERMISSION_FALLBACK_KEY_CHARS truncation
...
}
Also consider moving expensive fingerprinting behind Analyzed PR: #71707 at commit Last updated on: 2026-04-25T20:27:27Z |
|
Landed. Thanks @pashpashpash! |
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* codex harness mcp hook parity * tighten codex hook parity floor * prove security-style mcp hook blocking * bound native hook relay key handling * clarify permission relay defers to provider * harden native hook relay approvals * fix(agents): bound native hook relay JSON work budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
OpenClaw already had the generic native hook relay for Codex-owned shell, patch, and permission hooks. The remaining gap was MCP: Codex had recently added MCP hook payloads, but OpenClaw still documented MCP parity as future work and accepted older app-server versions that could not reliably emit those payloads.
This PR moves the tested Codex app-server floor to 0.125.0, which is the current stable line that includes MCP hook payload support. It also tightens version comparison so same-base prereleases or build-suffixed versions such as 0.125.0-alpha.2 and 0.125.0+custom do not satisfy the stable protocol floor.
The native hook relay now treats MCP payloads as first-class Codex-native tool events. PreToolUse can block MCP calls through OpenClaw before_tool_call, PostToolUse can surface MCP results through after_tool_call, and PermissionRequest can route MCP approval decisions through the existing OpenClaw approval path. If OpenClaw has no approval decision, the relay returns no decision and Codex continues through its own guardian or user approval path.
The proof is concrete:
The relay also got hardening fixes from review. Pending PermissionRequest approvals are keyed by tool call identity plus a stable content fingerprint, so a reused tool id with different tool input cannot inherit an old pending decision. Retained invocation history stores bounded payload snapshots instead of retaining full native tool output, while the active invocation still receives the full validated payload. The relay now also rejects overly broad JSON payloads before reading child values past its work budget, which keeps malformed or adversarial hook input from making the relay traverse unbounded data.
The Codex harness docs now reflect the updated v1 support contract: MCP block/observe and MCP permission routing are supported on the 0.125.0 floor, native tool argument mutation and native tool-result rewriting remain out of scope, and PermissionRequest no-decision behavior is called out explicitly.