Intelligence
AEW-020

An operation blocked in one syntactic form is authorized in an equivalent one

A policy checks the name of a consequential operation, or the identity of a resource, and works correctly wherever the operation or resource reaches the check in the form the check's own author tested. The identical operation or resource, produced by the same parser or the same addressing scheme, can instead be represented through a container, an encoding, or a transition format the policy's own logic does not recognize, and inside that alternate representation the same check never runs.

Status: publishedExecution Authority

Description

This weakness names a specific way a working check can still fail to cover what it was built to cover. A policy that validates an operation by its name, its type or its identity, or a resource by its address, is only as complete as the traversal or the classifier that walks whatever structure a parser, serializer or addressing scheme produces on the way to that operation or resource. Where a grammar, a schema, a wire format or an addressing standard offers more than one way to express the same underlying action or the same effective destination, the policy's own author may write and correctly test the check against the common or expected representation, while a distinct representation nests the identical operation one or more containers deeper, inside a tuple, a wrapped object, an alternate field, a synonym path, or embeds the identical resource inside a different literal encoding, such as a standardized transition address family carrying the same address in its low order bits, than the check was written to recognize. The check itself is not wrong; it is never asked the question, because the traversal or the classification that would carry the operation or the resource to it stops short of, or never opens, the representation it happens to be sitting in. This differs from an action executing with no applicable policy at all (AEW-001), where the gap is structural and no check exists for the action anywhere in the system: here a check exists, is correctly written, and demonstrably works on at least one representation of the same operation or resource. It differs from reachability substituting for authority in the absence of any check (AEW-008), which concerns a target being within reach with nothing gating it at all, not a specific check failing to extend across equivalent forms of one operation or one resource. It differs from an operation's authority being equated with authority over whatever it resolves against (AEW-013), which concerns a single sided target argument being reinterpreted in shape by the same actor within one request; here the operation or the resource itself is unchanged and its identity is not in question, only which of several equally valid representations carries it past or around an existing check.

The authority gap

The authority presented is whatever passes a check that exists, is correctly written, and is proven to work against at least one representation of the operation or resource. The authority required is a policy decision that reaches the operation or the resource regardless of which of several equivalent, parser produced or address encoded forms it takes, and the two are silently treated as the same guarantee.

Failure conditions

  • A policy validates a consequential operation, or a resource's identity, by inspecting a specific node, field, object type or numeric range produced by a parser, schema, serializer or addressing scheme.
  • The same underlying grammar, schema, wire format or addressing standard can express the identical operation or the identical effective resource through more than one distinct representation.
  • The policy's own traversal or classification logic recognizes representations only as far as the one it was written and tested against, without generically covering every container or encoding an alternate representation uses for the same operation or resource.
  • Nothing in the system treats an unrecognized or unopened container or encoding as a reason to deny by default; the operation or resource inside it is treated as though no policy applied.

Consequences shown by the evidence

  • A function, command or action a policy was built specifically to block executes anyway, with the same effect as if the policy did not exist, once expressed through an alternate representation of the identical operation.
  • A destination a policy was built specifically to keep out of reach is reached anyway, with the same effect as if the guard did not exist, once addressed through an alternate encoding of the identical resource.
  • An audit or design review that exercises only the common representation concludes the policy is complete, because every test it ran against that representation passed.

Detection signals

  • A security relevant traversal or classification function contains isinstance, type or numeric range checks enumerating specific node, container or address types rather than a generic descent or canonicalization covering everything the parser or addressing scheme can produce.
  • A fix for an incident adds a new branch or a new range to an existing traversal or classification function rather than introducing a new check, confirming the original check was correct but incompletely reached.
  • The same named operation, or the same effective resource, produces two different validation outcomes depending solely on which representation carried it to the check, with no other variable changed.

Known examples

  • Postgres MCP Pro's SafeSqlDriver validates a PostgreSQL function call's name against an explicit allow list whenever pglast represents the call as a FuncCall node, reached directly by the validator's own recursive walk, and this record confirmed directly that the same check correctly blocks pg_read_file, pg_ls_dir, pg_read_binary_file and pg_stat_file called this way. The identical function named inside a FROM clause instead parses as a RangeFunction node whose own functions attribute nests the same FuncCall one further container deep, inside a Python tuple pairing it with an alias, and the validator's recursive walk checks only whether each item in a list or tuple attribute is itself a syntax tree node, never unwrapping the nested tuple to find the FuncCall it contains. This record independently ran the real, unmodified validator from the affected v0.3.0 source and confirmed the same four functions all execute when reached this second way, while a write control, CREATE TABLE, remains correctly blocked throughout, isolating the gap to function name coverage on one grammar path. GHSA-cm87-gp55-7cgj formally assigns CVE-2026-85620 on 4 September 2026. A proposed fix, pull request 200, adds the missing traversal step; this record ran the patched validator directly and confirmed it closes the gap while leaving an allow listed FROM clause function, unnest, unaffected. As of this record, the pull request remains open and unmerged, and the identical bypass this record ran against the tagged v0.3.0 release also reproduces, confirmed directly, against the project's current default branch.
  • MCPHub's isBlockedIpv6 rejects an IPv6 destination by comparing its parsed, 128 bit numeric value against a fixed set of ranges, and this record confirmed directly, by reading the source at the commit immediately before the fix, that this comparison correctly blocked the unspecified and loopback addresses, the fe80::/10 link local range, the fc00::/7 unique local range, and both IPv4 mapped and IPv4 compatible embeddings, the address forms MCPHub's own existing test suite already exercised. Three IPv6 transition address families, each a standardized way of embedding the same 32 bit IPv4 address behind a distinct, fixed high order prefix, the NAT64 well known prefix 64:ff9b::/96, the deprecated 6to4 prefix 2002::/16, and the Teredo prefix 2001:0::/32, produced no match against any range the check tested for, so a private IPv4 address a caller could not name directly reached the same effective destination once named through one of these three encodings. GHSA-pr4x-3pc7-2fhw formally assigns CVE-2026-79749 on 23 August 2026. Remediation commit d382b36, merged in pull request 1069 as a56b4a17e25e2ebf09323a10882e1f83e445b2a8 and shipped in MCPHub 1.0.32, adds checks for exactly the three named families, this record confirmed directly against the diff, alongside two further ranges, site local addressing and multicast, that the same commit hardens without the advisory attributing them to this vulnerability specifically.
  • AWS Labs' postgres-mcp-server, an unrelated codebase maintained by a different organization from Crystal DBA's own Postgres MCP Pro, enforces its own read only mode through a keyword and function blocklist rather than an allow list, and GHSA-pwr4-hmph-gqgc, formally assigning CVE-2026-85787 on 4 September 2026 under CWE-184, Incomplete List of Disallowed Inputs, states that versions before 1.1.7 carried an incomplete list of disallowed inputs that could let an authenticated user's own submitted content modify data beyond the intended read only scope. This record fetched that advisory directly, and separately fetched the project's own current README, which states in its own words that this blocklist is a best effort, defense in depth mechanism, not a security boundary, naming obfuscation, quoted identifiers and new server or extension functions as categories a blocklist cannot enumerate in full, exactly the same shaped gap this weakness already names in general: a check that correctly blocks the representations and inputs it was tested against is not, on that basis, coverage of every representation or every input the same effect can be reached through. Unlike the two known examples above, this record could not independently reproduce the specific omitted input, since AWS's own advisory names no proof of concept and no source at the exact pre 1.1.7 version was reachable to this session; the corrected version, 1.1.7, was also already two months old at the advisory's own publication date, with five further releases shipped since, a materially different lifecycle position from Crystal DBA's own occurrence, where the identical bypass this record ran against a tagged release also reproduces, unpatched, against that project's current default branch.

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, and that a primitive bypassing its own toolCallRequest hook is invisible to policy. Postgres MCP Pro's restricted mode is concrete evidence for exactly the concern that admission names in the abstract: a mediation point that is present, correctly implemented and independently confirmed to work against one representation of a consequential operation still does not guarantee coverage of every representation the same underlying grammar can produce for it. This entry's own execution of the real, patched and unpatched validator against the same four functions supports the requirement that policy coverage be verified against the full range of representations a parser can produce, not only the one a mediation point's own author tested against. MCPHub's isBlockedIpv6 is the same admission read against a destination guard rather than a tool call hook: this entry's own direct reading of the pre fix and post fix source confirms a mediation point that correctly and completely covered every address form its own test suite exercised still left three standardized transition encodings of the same prohibited resource unmediated, supporting the requirement that coverage be verified against every representation an addressing standard can produce, not only the ones a guard's own author tested against.

    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. Postgres MCP Pro's SafeSqlDriver shows the inverse failure at a different layer, its own recursive AST traversal encountering a container it does not open, the tuple nested inside RangeFunction's own functions attribute, and treating what it never inspected as though it carried nothing requiring a check, rather than denying by default. This entry's own execution of the real validator confirms the same allow list check works correctly wherever the traversal does open the container it needs to, which is exactly why an unopened one silently passing is the more precise finding here, direct evidence for why a verifier's default posture toward a structure it does not fully parse matters generally, not only for this one draft's own constraint objects. MCPHub's isBlockedIpv6 supports the same requirement at a resource identity boundary rather than a syntax tree boundary: an IPv6 address encoded through the NAT64, 6to4 or Teredo transition prefixes was an unrecognized representation isBlockedIpv6 silently treated as unconstrained, returning false rather than denying by default, until the fix taught the function to recognize those three encodings as the blocked addresses they carry.

    View protocol evidence