Equivalent actions resolve to different authority decisions across execution surfaces
The identical consequential action, submitted through two execution surfaces that expose the same underlying capability, such as a direct SDK call and an MCP gateway wrapping the same broker, is enforced by two independently maintained checks rather than one shared rule. A fix that closes a gap on one surface does not, by itself, close the identical gap on the other, and the two surfaces apply different authority semantics to the same action until each is fixed on its own separate schedule.
Description
This weakness names what happens when a system that presents itself as enforcing one mandate in fact enforces it through more than one independently coded implementation, one per execution surface, and nothing keeps those implementations in agreement. Each surface's gate can be correctly written, tested and fixed on its own terms, and the system can still authorize the identical action differently depending only on which surface carried it. A defect discovered and repaired on one surface says nothing, by itself, about whether the sibling surface shares it, because the two were never one piece of enforcement to begin with. This weakness differs from enforcement wired to the caller rather than the shared executor, AEW-028: there, one shared executor function exists, and a check sits inside only one caller's own code path rather than inside the function every caller passes through, so some callers receive zero enforcement while others receive the genuine check. Here there is no single shared executor to place a check into. Each execution surface owns its own complete enforcement implementation, and both surfaces nominally enforce the same rule; the failure is that the two implementations drifted apart, not that one caller skipped a shared gate entirely. It differs from representation dependent authorization, AEW-020: there, one check fails to recognize that a differently encoded submission is the same operation it already knows how to evaluate. Here, each surface's own check correctly recognizes and evaluates the action submitted through it; the two checks simply disagree with each other about what that evaluation should conclude, because they are separately maintained. It is closely related to, and in this dataset's own evidence co-occurs with, quantitative mandate sized from the observed value, AEW-034: the specific defect that drifted out of sync between Vibe-Trading's two gates is an instance of AEW-034 on each surface individually, while AEW-035 names the further, systemic fact that fixing it on one surface left it live on the other for five days, evidence that no shared, canonical rule actually existed across both surfaces even though both were meant to enforce the same mandate.
The authority gap
The authority presented is a mandate's decision on one execution surface, verified and repaired there. The authority required is the identical mandate decision on every execution surface capable of submitting the equivalent consequential action, and a fix scoped to the surface where a defect was found is silently treated as though it protects every surface exposing the same underlying capability.
Failure conditions
- A system exposes the same consequential capability, such as placing a live order against a connected broker, through more than one execution surface, a direct SDK call, an MCP tool, an HTTP API or a CLI, each carrying its own gate applying nominally the same mandate.
- Each surface's gate is implemented and maintained separately rather than sharing one canonical enforcement function, so a defect in the intended shared rule can exist in one surface's implementation and not another's, or be fixed in one and not the other.
- A defect is found and fixed on one surface with no corresponding regression check run, or fix applied, against the sibling surface for the equivalent action.
- Nothing in the system's own tests or release process asserts that the identical canonical action and the identical mandate produce the identical authority decision across every surface capable of submitting it.
Consequences shown by the evidence
- The same principal, submitting the same action under the same mandate, is denied on one execution surface and allowed on another, so the mandate's actual protection depends on which surface the agent or the operator happened to use.
- A fix genuinely closes a defect on the surface it was written for while the identical defect remains live on every sibling surface, for as long as nobody checks.
- A security review of one execution surface's enforcement code finds nothing wrong there and does not, by itself, say anything about whether a sibling surface enforces the same rule.
Detection signals
- Two or more source files implement what their own comments describe as the same enforcement rule, worded near identically, for two different execution surfaces, with separate functions and separate tests.
- A fix commit or pull request for one execution surface's enforcement references, in its own commit message, an earlier fix to the identical defect on a different surface, without a corresponding test asserting the two surfaces now agree.
- A capability is reachable through a newer execution surface, an MCP or API wrapper added after a direct SDK path already existed, with no changelog or test evidence that the wrapper's own enforcement was audited against the direct path's rules at the time it was added.
Known examples
- Vibe-Trading fixed the identical buy-limit notional sizing defect twice, five days apart, on two separate execution surfaces exposing the same capability, placing a live order against a connected broker. Pull request 1312, merged 1 September 2026 as commit 789ca2b1, fixed the direct-SDK gate, src.live.sdk_order_gate._implied_notional, to price a buy limit at the larger of the live quote and the submitted limit price rather than the quote alone, and added limit_price as a field on the shared OrderIntent object every gate reads. Pull request 1361, merged 6 September 2026 as merge commit 07ad49f888c7ef658c773eeba4eb0a278d3bc8ea, fixed the MCP gate, LiveOrderGuardTool in src.live.order_guard together with the Robinhood connector's own extract_order_intent, for the identical defect. Even after OrderIntent carried limit_price, the MCP path's own extractor never mapped a limit_price keyword argument into it, and order_guard's own notional derivation never compared against it, so a buy limit submitted through the MCP tool continued to be sized at the quote alone for five more days after the direct-SDK path was fixed. Pull request 1361's own merge commit message describes the MCP gate's dead plumbing directly: the shared OrderIntent object already carried the limit_price field the SDK-side fix had added, but nothing on the MCP path read or wrote it until this second pull request. Both pull requests describe their fix in near identical terms, the worse of quote and limit, applied to two separately maintained functions in two separate modules, order_guard.py and sdk_order_gate.py, each with its own independently written test file. No test in the repository, before pull request 1361, asserted that the SDK gate and the MCP gate produce the same authority decision for the same mandate and the same submitted order. Independent verification for this record confirmed both merge commits, both diffs, and that the MCP path fix's own new tests fail against its pre-fix commit and pass against its fix, exactly as the SDK path fix's own tests had five days earlier.
- OpenAI's Codex CLI ships a PreToolUse hook mechanism whose configured JSON response format, a hookSpecificOutput object naming a permissionDecision of allow, deny or ask, is close to identical to Claude Code's own PreToolUse hook contract, naming the same three decisions. Two independent reports, read directly rather than through any automated summarization, establish that Codex's own current implementation enforces only one of the three: openai/codex's own issue 28437, opened 16 June 2026 by jignaciofernandez, states Codex's own current behavior directly, permissionDecision: ask is parsed but treated as unsupported, returning the error PreToolUse hook returned unsupported permissionDecision:ask, and requests native support for it, naming a prior pull request, 20702, closed for inactivity rather than rejection. A separate report, safishamsi/graphify issue 249, opened 12 April 2026 by sangdo90 against a third party tool's own generated Codex hook, states the identical mechanism for permissionDecision: allow, codex-cli 0.120.0 rejecting a hook response carrying it with the error PreToolUse hook returned unsupported permissionDecision:allow, for a JSON shape that had worked as the tool author intended on Claude Code. A hook JSON payload authored to escalate a specific tool call to human approval, or to grant an explicit allow, carries a materially different, in the ask case entirely absent, enforcement meaning depending only on which of the two hosts executes it, though which of two further outcomes an unsupported decision produces on Codex, the gated call proceeding regardless or the call itself being refused, is not established by either report and is recorded here as unknown rather than assumed either way. Recorded as a second known example of this weakness distinct from the Vibe-Trading pair above: there, two independently maintained enforcement implementations of one intended shared rule drifted apart through an ordinary coding defect since fixed on each surface in turn; here neither host's own implementation is broken relative to its own design, Codex's own hook contract simply does not yet enforce two of the three decisions Claude Code's identical hook shape honors, so a hook JSON payload's real protection depends on which of the two hosts happens to run it, exactly this weakness's own stated consequence, for as long as that capability gap stands.
Recorded instances
- AEV-2026-0046 Vibe-Trading's MCP live order gate priced a buy limit order at the quote alone, five days after the identical gap was fixed on the direct SDK path AESS 6.2 medium Confirmed
- AEV-2026-0065 Codex CLI's PreToolUse hook contract enforces only permissionDecision: deny; allow and ask are parsed and rejected as unsupported candidate Observed
Protocol evidence
Published authority architectures whose artifacts bear on the requirement this weakness names: which satisfy it, which expose a way past it, and which leave it unanswered.
- Missing requirement
Agent Control Standard (ACS)
OWASP GenAI Security Project, originally Zenity
Requirement The specification does not guarantee complete mediation of every consequential action a host can take
ACS's own stated conformance position, that a MUST level mediation requirement binds a host framework's own compliance rather than an independent enforcement mechanism, and that a permissive Guardian is a conformant but permissive deployment rather than a violation, already anticipates that mediation completeness is not guaranteed by the specification alone. Vibe-Trading's own two gates are a concrete instance of exactly that gap, one layer more specific than ACS's own framing: the same specification, or in this case the same intended mandate, was implemented as two independently maintained gates for two execution surfaces, the direct SDK path and the MCP path, and a fix to one carried no guarantee, and in fact no effect at all, on the other for five days. ACS's own conformance language does not go further and state that equivalent actions across a host's own multiple execution surfaces must be evaluated by one shared rule rather than parallel, independently maintained ones. Recorded as a requirement this dataset's evaluated protocols do not currently name, not as a defect in ACS's own stated, narrower conformance bar.
