Summary
At tangle-network/agent-gateway commit
4d1429c4b1947bd4ca65472aadfdfd89d0daddeb, the A2A JSON-RPC endpoint exposes
both authenticated message methods and task-control methods on POST /:slug.
message/send and message/stream call the shared authenticateAndGuard
pipeline, which resolves a trusted consumerId. However, tasks/get,
tasks/cancel, tasks/resubscribe, and
tasks/pushNotificationConfig/{set,get,list,delete} dispatch directly to task
store operations by bare task id.
The authority path is:
Alice authenticated message/send
-> Task persisted by taskId/contextId without consumer owner binding
Anonymous caller
-> tasks/get(taskId) reads Alice task/artifact
-> tasks/pushNotificationConfig/set(taskId, attacker URL)
-> tasks/cancel(taskId)
-> gateway posts full task body to attacker push URL
Affected Target Verified
- Repository:
https://github.com/tangle-network/agent-gateway
- Commit verified:
4d1429c4b1947bd4ca65472aadfdfd89d0daddeb
- Package version in checkout:
0.7.0
- Components:
src/middleware.ts
src/a2a/handler.ts
src/a2a/task-store.ts
src/a2a/push-notifications.ts
src/dispatch.ts
- Evidence level: target-package replay against the built Hono app with source
anchors and negative-control policy
Preconditions
- A deployment exposes the A2A JSON-RPC route.
- A victim creates or owns an A2A task.
- An attacker can learn, guess, choose, or collide with a task id. The gateway
accepts caller-supplied task ids for new tasks, and task ids are also returned
in normal A2A responses/headers.
- Push impact requires
GatewayConfig.a2a.pushStore to be enabled. Direct
unauthenticated task read/cancel does not require push support.
Steps To Reproduce
From this report directory:
Expected vulnerable result:
{
"verdict": "fail-under-consumer-bound-a2a-task-control-and-push-policy",
"missingAnchors": []
}
The replay executes the target's built Hono app:
- Alice authenticates with
Authorization: Bearer sk_agent_alice.
- Alice creates
task_alice_private_get and receives a private artifact.
- An anonymous request calls
tasks/get for that task id and receives the
full task/artifact.
- Alice creates
task_alice_private_paused, which enters input-required.
- An anonymous request registers a push callback for Alice's paused task.
- An anonymous request cancels Alice's paused task.
- The gateway posts the full canceled task to the attacker callback URL.
Observed oracle facts include:
{
"anonymousGetStatus": 200,
"anonymousGetPrivateArtifactText": "ALICE_PRIVATE_RESULT=flight-772",
"anonymousPushSetStatus": 200,
"anonymousCancelState": "canceled",
"pushedTaskId": "task_alice_private_paused",
"pushedTaskState": "canceled"
}
Technical Details
Source facts validated by the oracle:
POST /:slug routes all A2A JSON-RPC methods into handleJsonRpc.
message/send and message/stream enter authenticateAndGuard.
tasks/get, tasks/cancel, tasks/resubscribe, and push-config methods do
not pass through authenticateAndGuard.
authenticateAndGuard resolves a trusted consumerId, but persisted A2A
Task objects do not store an owner/consumer field.
- New tasks are persisted by caller-supplied or gateway-generated
taskId and
contextId.
tasks/get returns the full task object by bare task id.
tasks/cancel mutates task state by bare task id.
tasks/pushNotificationConfig/set checks that the task exists and that the
callback URL is a string, then stores the supplied config.
- Push delivery posts the full task body to the stored callback URL.
Expected Behavior
Task-control and push-config operations should be authenticated and authorized
against the same consumer, tenant, agent, or payment authority that created the
task. taskId should identify the object, not authorize access to it.
Actual Behavior
The task-control methods operate on bare task ids without an authenticated
caller. An anonymous caller can read a task, cancel a non-terminal task, and
register a push receiver on a task created by an authenticated user.
Impact
Depending on deployment and task contents, this can cause:
- unauthorized task history/artifact disclosure through
tasks/get or
tasks/resubscribe;
- unauthorized task lifecycle mutation through
tasks/cancel;
- push receiver spoofing and externalization of full task bodies to an
attacker-controlled URL;
- attacker-controlled webhook authentication headers being sent by the gateway
during push delivery.
Push URL validation is also weak in this path: the replay stores an http://
URL. The main reportable boundary is missing task authority; URL validation
should be fixed as part of push receiver hardening.
Suggested Fix
- Run all A2A JSON-RPC methods through a shared authentication step.
- Persist task ownership metadata such as
consumerId, key id, tenant, or
payment signer with each task.
- Check read/write authority before
tasks/get, tasks/cancel,
tasks/resubscribe, and every push-config operation.
- Bind push configs to the same task owner authority and require callback URL
policy, preferably HTTPS plus SSRF-safe validation.
- Add Alice/Bob/anonymous regression tests for
tasks/get, tasks/cancel,
tasks/resubscribe, and push-config CRUD.
Attachments
attachments.zip
Summary
At
tangle-network/agent-gatewaycommit4d1429c4b1947bd4ca65472aadfdfd89d0daddeb, the A2A JSON-RPC endpoint exposesboth authenticated message methods and task-control methods on
POST /:slug.message/sendandmessage/streamcall the sharedauthenticateAndGuardpipeline, which resolves a trusted
consumerId. However,tasks/get,tasks/cancel,tasks/resubscribe, andtasks/pushNotificationConfig/{set,get,list,delete}dispatch directly to taskstore operations by bare task id.
The authority path is:
Affected Target Verified
https://github.com/tangle-network/agent-gateway4d1429c4b1947bd4ca65472aadfdfd89d0daddeb0.7.0src/middleware.tssrc/a2a/handler.tssrc/a2a/task-store.tssrc/a2a/push-notifications.tssrc/dispatch.tsanchors and negative-control policy
Preconditions
accepts caller-supplied task ids for new tasks, and task ids are also returned
in normal A2A responses/headers.
GatewayConfig.a2a.pushStoreto be enabled. Directunauthenticated task read/cancel does not require push support.
Steps To Reproduce
From this report directory:
Expected vulnerable result:
{ "verdict": "fail-under-consumer-bound-a2a-task-control-and-push-policy", "missingAnchors": [] }The replay executes the target's built Hono app:
Authorization: Bearer sk_agent_alice.task_alice_private_getand receives a private artifact.tasks/getfor that task id and receives thefull task/artifact.
task_alice_private_paused, which entersinput-required.Observed oracle facts include:
{ "anonymousGetStatus": 200, "anonymousGetPrivateArtifactText": "ALICE_PRIVATE_RESULT=flight-772", "anonymousPushSetStatus": 200, "anonymousCancelState": "canceled", "pushedTaskId": "task_alice_private_paused", "pushedTaskState": "canceled" }Technical Details
Source facts validated by the oracle:
POST /:slugroutes all A2A JSON-RPC methods intohandleJsonRpc.message/sendandmessage/streamenterauthenticateAndGuard.tasks/get,tasks/cancel,tasks/resubscribe, and push-config methods donot pass through
authenticateAndGuard.authenticateAndGuardresolves a trustedconsumerId, but persisted A2ATaskobjects do not store an owner/consumer field.taskIdandcontextId.tasks/getreturns the full task object by bare task id.tasks/cancelmutates task state by bare task id.tasks/pushNotificationConfig/setchecks that the task exists and that thecallback URL is a string, then stores the supplied config.
Expected Behavior
Task-control and push-config operations should be authenticated and authorized
against the same consumer, tenant, agent, or payment authority that created the
task.
taskIdshould identify the object, not authorize access to it.Actual Behavior
The task-control methods operate on bare task ids without an authenticated
caller. An anonymous caller can read a task, cancel a non-terminal task, and
register a push receiver on a task created by an authenticated user.
Impact
Depending on deployment and task contents, this can cause:
tasks/getortasks/resubscribe;tasks/cancel;attacker-controlled URL;
during push delivery.
Push URL validation is also weak in this path: the replay stores an
http://URL. The main reportable boundary is missing task authority; URL validation
should be fixed as part of push receiver hardening.
Suggested Fix
consumerId, key id, tenant, orpayment signer with each task.
tasks/get,tasks/cancel,tasks/resubscribe, and every push-config operation.policy, preferably HTTPS plus SSRF-safe validation.
tasks/get,tasks/cancel,tasks/resubscribe, and push-config CRUD.Attachments
attachments.zip