fix: sanitize internal error messages in transport handlers - #1046
fix: sanitize internal error messages in transport handlers #1046ez-lbz wants to merge 5 commits into
Conversation
ehsavoie
left a comment
There was a problem hiding this comment.
There are still some InternalError leaking messages:
- reference/jsonrpc/src/main/java/.../A2AServerRoutes.java:340 — new InternalError(t.getMessage())
- reference/rest/src/main/java/.../A2AServerRoutes.java:309, 427, 461, 495, 605, 636, 681, 714 — new InternalError(t.getMessage())
There was a problem hiding this comment.
This should be sanitized s well
The reference JSON-RPC and REST route handlers still propagated the raw exception message to clients via new InternalError(t.getMessage()). Use the generic InternalError message and log the original throwable so server-side observability is preserved.
|
Good catch — the transport handlers were fixed but the reference server routes were missed. All 9 remaining Testing: |
| error = new A2AErrorResponse(new JSONParseError(e.getMessage())); | ||
| } catch (Throwable t) { | ||
| error = new A2AErrorResponse(new InternalError(t.getMessage())); | ||
| LOG.error("Failed to process request", t); |
There was a problem hiding this comment.
Maybe use the same message as in the handlers:
"Internal error while processing request"
| import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; | ||
| import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; | ||
| import static org.a2aproject.sdk.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; | ||
| import org.slf4j.Logger; |
There was a problem hiding this comment.
Maybe move this down after java imports
| response = jsonRestHandler.sendMessage(context, extractTenant(rc), body); | ||
| } catch (Throwable t) { | ||
| response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); | ||
| LOG.error("Failed to process request", t); |
There was a problem hiding this comment.
Maybe use the same message as in the handlers:
"Internal error while processing request"
| import static org.a2aproject.sdk.transport.rest.context.RestContextKeys.METHOD_NAME_KEY; | ||
| import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; | ||
| import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; | ||
| import org.slf4j.Logger; |
There was a problem hiding this comment.
Move this down after the java imports
|
@ez-lbz some small fixes before I can merge |
… messages
- RestHandler: the response-serialization failure path leaked the
InvalidProtocolBufferException message; sanitize it and log the throwable.
- Reference JSON-RPC/REST routes now log the same message as the transport
handlers ('Internal error while processing request') and place the
slf4j imports after the java imports.
|
All five points addressed:
Testing: |
What changed
1. Sanitize internal error messages in the JSON-RPC handler
Problem:
JSONRPCHandlerconverted every unexpected (non-A2AError) exception intonew InternalError(t.getMessage()), forwarding the raw exception message — often containing file paths, library names, or class names — to the client in the JSON-RPC error payload (CWE-209, information disclosure / server fingerprinting).Fix (transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java):
LOGGER(java.util.logging) and a privateinternalError(Throwable)helper that logs the full exception server-side (Level.SEVERE) and returnsnew InternalError("Internal error")with a generic, client-safe message.new InternalError(...getMessage())sites (onMessageSend, onMessageSendStream, onSubscribeToTask, cancel/get/list tasks, push-notification config endpoints, extended agent card, and the streaming subscriberonErrorpath).Fix (transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java):
testOnMessageSendSanitizesUnexpectedException— a mockedRuntimeExceptionwith a sensitive message yields anInternalErrorwhose message is"Internal error"and does not contain the sensitive text.2. Sanitize internal error messages in the REST handler
Fix (transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java):
internalError(Throwable)helper (logs atSEVERE, returnsnew InternalError("Internal error")) and replaced all 13new InternalError(...getMessage())sites across send/cancel/get/list/subscribe/push-config/agent-card endpoints, including the streaming error paths.Fix (transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java):
testSendMessageSanitizesInternalError— asserts a 500 response whose message is"Internal error"(no sensitive text leaked).3. Sanitize internal error messages in the gRPC handler
Problem:
GrpcHandler.handleInternalErrorsentt.getMessage()in the gRPC error description, leaking internal exception details to the client.Fix (transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java):
handleInternalErrornow logs the full exception atSEVEREand callshandleErrorwithnew InternalError("Internal error"), so the gRPC status description carries only the generic message.Fix (transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java):
testOnMessageInternalErrorIsSanitized— a mockedRuntimeExceptionyields gRPCINTERNALwith description"Internal error"(no sensitive text).Note: exceptions that are already
A2AError(includingInternalErrorthrown by the request handler) still flow through unchanged — sanitization applies to unexpected non-A2A exceptions. Thecompat-0.3module has its own copies of the handlers and was intentionally left unchanged (out of scope).Testing
mvn -pl transport/jsonrpc,transport/grpc,transport/rest test— 127 tests run, 0 failures, 1 skipped (BUILD SUCCESS): JSON-RPC 49, gRPC 41, REST 37, including the 3 new sanitization regression tests.mvn -pl reference/jsonrpc test— 198 tests run, 0 failures, 0 skipped (BUILD SUCCESS).