Intelligence
AEW-032

A malformed authority restriction is parsed the same as no restriction at all

An authority bearing field meant to restrict which actions or resources a caller may use is present, non empty, and structurally invalid: neither the shape a schema documents nor a value carrying any interpretable restriction. Rather than being rejected, the value reaches the identical permissive result the same code returns when the field is absent entirely, silently discarding the restriction the caller's own present field expressed an intent to make.

Status: publishedExecution Authority

Description

This weakness names a specific way a parser that correctly recognizes every valid shape of an authority bearing field can still fail to gate what it was built to gate. A field documented to accept, say, a plain array or a structured object is tested against each recognized shape in turn, and a value matching neither is not rejected as invalid; it falls through to whatever branch the same function uses for the field's own genuine absence, because that branch is written as the function's default rather than as a case reserved specifically for absence. The check itself is not wrong about the shapes it does recognize, and this is not a bypass of a working check through an alternate representation of the same operation, the shape this registry's own representation dependent authorization weakness, AEW-020, already names: there, an operation or a resource the check was built to cover reaches it through a container or an encoding the check never opens, and the identical operation, reached the ordinary way, is correctly blocked. Here nothing is nested inside anything; the value itself is simply not one of the documented forms, and no alternate representation of it would be valid either. It also differs from an explicit denial discarded by a compiler's own generic defaulting helper, AEW-022: that weakness lives at configuration compile time, before any request exists, and concerns a valid, meaningful, falsy value, such as a boolean false, being conflated with an unset key by a template engine's own emptiness test. Here the value is invalid, not falsy, the layer is per request runtime parsing rather than deployment time compilation, and there is no template or compiler standing between the caller and the check at all. The distinguishing shape of this weakness is narrower and more specific than either: a parser with a genuine default branch for absence, reached a second time by any value its own type checks cannot classify, so that failing to interpret a restriction and never having been asked for one become, at the only point that matters, the same fact.

The authority gap

The authority required is whatever restriction the caller's own present, non empty field expressed, however incorrectly shaped. The authority presented, once the value fails to match any shape the parser recognizes as valid, is silently substituted for the authority that would apply had the caller never supplied the field at all, treating a failed interpretation as equivalent to an unexpressed intent rather than as an intent the system could not honor and should have refused.

Failure conditions

  • An authority bearing field accepts more than one valid, documented shape, and the parser tests the field's value against each recognized shape in turn.
  • A value matching none of the recognized shapes is structurally possible for a caller, or a caller's own client library, to produce, whether by a shape mismatch, a serialization choice, or a member of the wrong type nested one level inside an otherwise recognized shape.
  • The code path reached when a value matches no recognized shape returns the identical result the same function returns for the field being entirely absent, rather than a distinct invalid, rejected or fail closed result.
  • The normalized, permissive result produced from the invalid input is used to resolve the caller's own effective authority before any later boundary can evaluate or reject the original, unparsed value.

Consequences shown by the evidence

  • A caller who supplies a restriction meant to exclude a class of action or resource instead receives the same unrestricted authority an entirely unrestricted request would have received, with no error, warning or rejected request indicating the restriction never took effect.
  • A downstream validator that would otherwise reject the caller's own original, malformed field never receives it, once an earlier stage has already rewritten the request using the unrestricted interpretation the malformed value produced.
  • An operator reviewing only the rewritten request, or only a system's eventual selection among what it exposed, has no artifact in front of them showing a restriction was ever attempted, let alone that it silently failed to apply.

Detection signals

  • An authority bearing field's own extraction function has a final, unconditional branch returning the identical permissive value the function also returns for the field's own absence, reached whenever a value fails every earlier, more specific type check.
  • A structured authority object's own per member extraction reads a value through an optional chain, such as an and_then or equivalent, that quietly yields none for any wrong typed value, with nothing in the parsed result distinguishing a wrong type from an absent member.
  • A test suite for the field exercises every documented valid shape and the absent case, but no wrong top level type and no wrong typed member of an otherwise valid object appears anywhere in it.

Known examples

  • GitHub issue 939 against praxis-proxy/ai, opened 7 September 2026, labelled human reviewed, triage accepted and area ai for milestone v0.4.0, and independently corroborated by this session's own direct reading and execution of the affected source at the repository's current default branch, commit 84ddcc4ef0e33a6c6006a2d5264069fde96c5dfc: extract_allowed_tools, resolving an OpenAI Responses API MCP tool entry's own allowed_tools field, tests the value against a JSON array branch and a JSON object branch and, for anything matching neither, a bare string such as safe among them, falls through to the same AllowedTools::unrestricted() its own first line returns for an absent field. This session confirmed the same collapse recurs one level inside the documented filter object form: extract_from_filter_object reads its own tool_names and read_only members through an and_then chain yielding none for either member whenever its value is present but the wrong JSON type, again indistinguishable in the parsed result from the member being absent. This session copied these exact, unmodified functions into a standalone program and ran them directly against a deterministic local fixture, a read only tool and a non read only tool, confirming that a bare string allowed_tools value resolves both tools as eligible, identically to an absent allowed_tools field, while the documented array form correctly resolves only the one tool it names. This session separately read rewrite_request_body and confirmed a resolved MCP entry, and the original allowed_tools value it carried however malformed, is always removed from the outgoing request and replaced with concrete function tool definitions computed from the unrestricted interpretation, so a downstream schema at the inference backend that might otherwise reject the malformed value never receives it. No merged fix was found on the repository's current default branch as of this session's verification, and the exact commit the issue's own review cites, 3cfddbcbf4d6adcab02d8257bbdb272981c433c7, resolves to no such commit against the repository as read directly by this session, a discrepancy recorded here as unresolved.

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.

  • Supports 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 conformance document states directly that the specification does not guarantee complete mediation of every consequential action a host can take. Praxis Proxy's own resolver is concrete evidence for a narrower version of the same admission: a mediation point, extract_allowed_tools, is present, is reached on every request, and correctly recognizes both documented restriction shapes, yet still does not mediate a value that matches neither shape, because its own fallback branch for that case is the identical branch written for the restriction never having been attempted at all. This entry's own execution of the real function against a local fixture supports the requirement that a mediation point's own coverage be verified against every value a caller can supply, not only the shapes its own author documented.

    View protocol evidence

  • Supports requirement

    Cedulon, an audit layer for agent to agent commerce

    E. C. Dogru, individual submission to the IETF

    Requirement The policy decision point fails closed

    Cedulon's own specification requires that a policy decision point resolve to deny when it is unreachable, uninitialized or failing, so a failure inside the check itself cannot quietly relax the limit it exists to enforce. Praxis Proxy's own extract_allowed_tools shows the same principle unmet one layer earlier, at parsing rather than at decision time: the function does not fail or become unreachable, it runs to completion and reaches a branch built for absence whenever it cannot classify the value it was given, confirmed directly by this entry's own reading and execution of the source. This is evidence for why a fail closed default belongs at every point an authority bearing value can go uninterpreted, parsing included, not only at the decision point the draft's own text names.

    View protocol evidence

  • Supports requirement

    Verifiable Attenuated Delegation for AI Agent Chains (draft-asor-wimse-agent-delegation-chain)

    Rafael Asor, Attenu

    Requirement A verifier encountering an unrecognized constraint type must deny rather than treat it as unconstrained

    This draft's own verified requirement is that a verifier encountering an unrecognized constraint type must deny rather than treat it as unconstrained, so that a newer, unrecognized restriction is never silently read as no restriction at all. Praxis Proxy's own extract_allowed_tools shows the same failure at a different boundary, an OpenAI Responses API MCP tool entry's own allowed_tools field rather than a delegation token's own constraint array: a present value matching neither documented shape is not denied, it reaches the identical AllowedTools::unrestricted() the function returns for the field's own absence, confirmed directly by this entry's own reading and execution of the real, unmodified function against a deterministic local fixture. This is direct evidence for why the draft's own fail closed requirement matters as a general parsing discipline for any authority bearing field, not only for one draft's own constraint objects.

    View protocol evidence