fix: sanitize internal error messages in JSON-RPC and gRPC paths - #1183
Open
ez-lbz wants to merge 7 commits into
Open
fix: sanitize internal error messages in JSON-RPC and gRPC paths#1183ez-lbz wants to merge 7 commits into
ez-lbz wants to merge 7 commits into
Conversation
Agent exceptions are now sanitized server-side (internal details are logged, not exposed to clients). The integration scenario that asserted the raw exception message leaks to the client is updated to expect the generic InternalError instead, catching the base A2AError so the check holds across transports.
🧪 Code Coverage (vs
|
| Base | PR | Delta | |
|---|---|---|---|
| src/a2a/client/transports/grpc.py | 92.75% | 91.30% | 🔴 -1.45% |
| src/a2a/server/events/event_queue_v2.py | 91.79% | 91.28% | 🔴 -0.51% |
| src/a2a/server/request_handlers/grpc_handler.py | 95.42% | 96.88% | 🟢 +1.45% |
| src/a2a/utils/telemetry.py | 91.47% | 90.70% | 🔴 -0.78% |
| Total | 93.00% | 92.98% | 🔴 -0.02% |
Generated by coverage-comment.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
1. Stop leaking internal exception details in JSON-RPC errors
Problem: The JSON-RPC dispatcher (
src/a2a/server/routes/jsonrpc_dispatcher.py) embedded the raw exception text into client-visible errors in four places: base request validation (InvalidRequestError(data=str(e))), param parsing (InvalidParamsError(data=str(e))), the unhandled-exception path (InternalError(message=str(e))), and the SSE stream error path (InternalError(message=str(e))). The generic defensive conversion in_generate_error_response()also usedInternalError(message=str(error)). This leaks internal paths, library versions, and stack details to clients (fingerprinting / information disclosure).Fix (src/a2a/server/routes/jsonrpc_dispatcher.py):
logger.exception(...)._generate_error_response()converts unknown errors to a bareInternalError()("Internal error") instead of embeddingstr(error).2. Stop leaking unknown exception details in the gRPC handler
Problem:
GrpcHandler(src/a2a/server/request_handlers/grpc_handler.py) leaked exception details in two ways: non-A2A exceptions were not caught by_handle_unary/_handle_streamand propagated to the gRPC framework with their message text; and theabort_context()fallback sentUnknown error type: {error}, embedding the exception repr.Fix (src/a2a/server/request_handlers/grpc_handler.py):
_handle_unaryand_handle_streamnow catch genericException, log it, and abort withInternalError(INTERNAL / "Internal error").abort_context()'s fallback now logs the unknown error and aborts with a generic"Unknown error"message instead of embedding the error repr.Testing
./.venv/Scripts/python -m pytest tests/server/routes/test_jsonrpc_dispatcher.py tests/server/request_handlers/test_grpc_handler.py tests/server/test_integration.py -q→ 97 passed (includes new sanitization tests for the unhandled-exception, malformed-params and invalid-base-request paths, plus gRPC unhandled-exception and unknown-A2A-error paths; all assert the internal text does not appear in the response)../.venv/Scripts/python -m pytest tests/compat/v0_3/ -q→ 250 passed (v0.3 compat unaffected).tests/server/test_integration.py::test_unhandled_exceptionto assert the generic"Internal error"message and the absence of the exception text (previously it asserted the leaked message)../.venv/Scripts/python -m ruff checkon modified files: clean.Internal error/Unknown error. Error codes are unchanged.