A tool's stored response transformation runs with the gateway's own authority
A field attached to a tool definition, meant only to reshape that tool's response, is evaluated as an executable program at invocation time. Whoever configured the tool wrote the program; whoever the runtime later authorizes to invoke the tool triggers it, and the program runs with the gateway's own process authority rather than a scope either principal actually holds.
Description
Two authority decisions again hide inside what looks like one, in a shape distinct from an operation reaching a wider target (AEW-013) or an objective silently authorizing a wider action (AEW-002). Deciding that a principal may configure a tool, setting whatever fields the tool's schema accepts, is one decision. Deciding that a different principal, later, may invoke that tool is a second, independently checked decision in systems that separate the two permissions correctly. What neither decision addresses is a third question hiding inside the first: whether a field the schema accepts as configuration is, once the runtime reaches it, a program rather than data, and if so, under whose authority that program should run. When a gateway or intermediary evaluates such a field with its own full process authority, an invoking principal's authorized action silently triggers a second, unauthorized execution event that neither the tool's configurer nor its invoker independently approved. This differs from delegated authority inherited without attenuation (AEW-006), which concerns one agent handing standing authority or a shared credential to another agent or sub agent; here no agent delegates to another agent at all, and the two principals may never interact. The authority instead moves sideways, from a configuration time decision into an invocation time execution, carried by a field neither principal's own permission check was written to treat as executable.
The authority gap
The authority required to execute a program against the gateway's own process state is authority nobody independently granted that program. The authority presented is whatever the gateway itself already holds, inherited automatically because the program sits inside a field on a tool an invoking principal was separately, correctly authorized to call.
Failure conditions
- A tool or resource definition carries a field that the runtime evaluates as a program (a filter, a template, a transform, a mapping) rather than treating as inert configuration.
- The principal authorized to configure that field and the principal later authorized to invoke the tool are, or can be, different, with no independent authorization decision governing the stored program itself.
- The runtime evaluates the program with the same process authority the gateway or intermediary itself holds, rather than a capability scoped to what a response transformation requires.
Consequences shown by the evidence
- A caller authorized only to invoke a tool triggers a program authored by a different principal with configuration authority, and that program runs able to read the gateway's own process environment, including secrets held there.
- A stored transformation field that reads as passive configuration in a schema is, once the runtime evaluates it, a second execution path alongside the tool call itself, unscoped by whatever authority the invoking principal actually holds.
Detection signals
- A tool or resource definition schema accepts a field whose value is compiled or evaluated as a program, rather than only looked up, templated with fixed substitutions, or used as a literal.
- Write time validation exists for such a field, but invocation still evaluates rows persisted before that validation shipped, with no revalidation at invocation time.
- The environment or host state reachable from inside the transformation matches the gateway's own process environment rather than a scoped, cleared subset of it.
Known examples
- IBM ContextForge MCP Gateway's jsonpath_filter field on a REST tool is a jq program, set by a caller holding the tools.create or tools.update permission and run by extract_using_jq against that tool's response every time a separate caller, holding only the tools.execute permission, invokes it, confirmed directly by this desk's own reading of the affected source. Before the fix merged as pull request 6205 and shipped in release v1.0.8, nothing restricted that program from calling jq's own env, $ENV, input, inputs, input_filename, input_line_number, $__loc__, debug, stderr, include, import or modulemeta builtins, so a filter written once by the configuring principal could read the gateway's own process environment on every later invocation by an entirely different principal, formally assigned CVE-2026-18486 on 4 September 2026. The fix now validates the field at write time and again at invocation time, so a filter already stored before the fix ships cannot bypass the new policy, and runs an accepted filter inside a forked worker whose own environment is cleared before it compiles, bounded by a timeout, on Linux; ContextForge's own documentation states the sandbox is silently inactive on any other platform, where the static check alone remains the only protection.
- Amazon CodeCatalyst's blueprints SDK reads a project's own .ownership-file to decide, per path, which blueprint may modify it during resynthesis, and the file's owner field carries two structurally different meanings decided purely by the merge strategy identifier next to it, confirmed directly by this desk's own reading of the affected source. For every identifier except the reserved word local, owner is only ever compared as an identity string. For the identifier local, the same field position is instead read by constructLocalStrategy as a custom merge driver command pattern and, in every version through 0.3.155, handed whole to a shell with no character check at all, so a committer's own choice of value for an ordinary looking ownership field could carry shell metacharacters straight into the resynthesis environment's own command interpreter. Formally assigned CVE-2026-85012 on 3 September 2026. The fix, shipped in version 0.3.156 and confirmed by this desk as unchanged on the current default branch, version 0.3.159, removes the shell from the execution path entirely, calling execFileSync with a pre split argument array, and separately rejects a local owner value outside a narrow allow list before that call is ever reached.
Recorded instances
- AEV-2026-0031 IBM ContextForge's stored jq response filter ran with the gateway's own process authority (CVE-2026-18486) AESS 8.0 high Confirmed
- AEV-2026-0052 Amazon CodeCatalyst blueprints ran a project's own ownership field through a shell with no validation (CVE-2026-85012) AESS 7.1 high Confirmed
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, naming a primitive that bypasses its own toolCallRequest hook as invisible to policy. IBM ContextForge's stored jq filter is concrete evidence for a stage this admission does not itself name: a consequential action, evaluating an executable program against gateway process state, occurring after a tool call has already been authorized and mediated, inside a response transformation step neither the tool's own invocation permission nor a hook fired at the moment of the call was written to examine. This entry's own reading of the pre fix evaluation path supports the requirement that mediation be evaluated against every stage capable of consequential effect, not only the moment a tool call itself is authorized.
- Supports requirement
ARC, Agentic Runtime Control
Britive
Requirement Elevated privilege is documented as minted directly in a target system through its own native API and revoked automatically when a task ends, with credential brokering as a separate path for systems that require one
Britive's own documented model brokers or mints credentials ephemerally and scoped to a task, rather than leaving a standing credential ambiently reachable by whatever process happens to run. IBM ContextForge's pre fix jsonpath_filter is the failure that principle answers, made concrete: a stored program, once triggered, read the gateway's own standing process environment directly, with no brokering step and no scope narrower than the gateway's own full authority in between. The shipped fix's own cleared, sandboxed worker is a narrower, response transformation scoped instance of the same corrective this property already names for a broader class of runtime credential access, supporting the requirement that executed logic reach only a scoped, brokered capability rather than a gateway's own ambient environment.
