Skip to content

Bound A2A unary RPC errors so remote HTTP bodies cannot enter tool envelopes - #360

Merged
tylerreckart merged 8 commits into
mainfrom
fix/a2a-rpc-http-error-bound
Sep 21, 2026
Merged

tylerreckart merged 8 commits into
mainfrom
fix/a2a-rpc-http-error-bound

Conversation

@cursor

@cursor cursor Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Client::rpc concatenated the entire non-200 HTTP body into err_out:

err_out = "HTTP " + status + ": " + r.body;

/a2a call (the production outbound path via make_a2a_invoker → send_message) copies that string into the calling agent's tool envelope. A verbose or hostile remote can return megabytes of HTML/JSON — stack traces, echoed cookies, login pages — which then persist in conversation history and are visible to the model. JSON-RPC error.message on HTTP 200 was similarly unbounded and could contain CR/LF.

This is the same class as provider-error sanitization on the inbound/delegation paths (#311 / #321), for the outbound A2A client.

Fix

  • format_rpc_http_error reports HTTP <status> plus a JSON-RPC error.message (or top-level string error) when the body is JSON.
  • Raw HTML/text bodies are omitted entirely (status only).
  • sanitize_rpc_error_text drops CR/LF/NUL/other ASCII controls and UTF-8-safely truncates at 200 bytes.
  • HTTP-200 JSON-RPC errors use the same clip via format_rpc_json_error.
  • Isolated to src/a2a/types.cpp + include/a2a/types.h + src/a2a/client.cpp + tests/test_a2a.cpp.

Tests

unit_a2a:

  • HTML / 8 KiB garbage / empty body → HTTP 500 / HTTP 502 / HTTP 401 with no body leak.
  • JSON-RPC and {"error":"…"} keep a short detail.
  • Controls stripped; 200-byte exact string unchanged; 201 bytes and a trailing 2-byte UTF-8 character truncate cleanly.

Suite 29/29 locally (215 assertions) + ASan + UBSan. arbiter compiles.

Independently mergeable against main (0456350). git merge-tree --write-tree vs #321, #326, #331, #342, #351, #354, #358, and #359 is CLEAN. Do not re-fix #321–#359.

Open in Web View Automation 

Note

Medium Risk
Changes what agents see on A2A failures (shorter, sanitized errors) but reduces risk of unbounded or sensitive remote content entering persisted conversation history.

Overview
Outbound A2A unary RPC errors are capped so hostile or verbose remotes cannot flood agent tool results and conversation history.

Client::rpc previously built err_out as HTTP <status>: <full body>; /a2a call forwards that string into the caller’s tool envelope. Non-200 responses now use format_rpc_http_error: status only when the body is plain HTML/text, or status plus a parsed JSON-RPC error.message (or top-level string "error") when the body is JSON. HTTP 200 JSON-RPC failures go through format_rpc_json_error with the same rules.

Shared sanitize_rpc_error_text strips CR/LF and other controls, normalizes tabs, and UTF-8–safely truncates at 200 bytes (kMaxRpcErrorDetail). Helpers live in types.h / types.cpp so unit_a2a can test bounds without the HTTP client. CHANGELOG documents the fix; test_a2a covers HTML omission, JSON detail retention, control stripping, and truncation.

Reviewed by Cursor Bugbot for commit 0fc19c0. Bugbot is set up for automated code reviews on this repo. Configure here.

…velopes

Client::rpc concatenated the entire non-200 response body into err_out.
/a2a call copies that string into the calling agent's tool result, so a
verbose or hostile remote could dump unbounded HTML/JSON (and any secrets
it echoed) into conversation history. Report HTTP <status> plus a
200-byte single-line JSON-RPC error.message when present.

Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
@tylerreckart
tylerreckart marked this pull request as ready for review September 21, 2026 12:58
@tylerreckart
tylerreckart enabled auto-merge (squash) September 21, 2026 12:58
cursoragent and others added 6 commits September 21, 2026 12:59
Keep both Unreleased changelog bullets: A2A unary HTTP error bounding
and the already-landed --connect base URL query/userinfo reject (#366).

Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
Main landed the LaTeX recursion-depth and key-file O_NOFOLLOW notes
alongside this PR's A2A unary HTTP error bound.

Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
…r-bound

Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
@tylerreckart
tylerreckart merged commit ca24570 into main Sep 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants