Skip to content

[Server] Handle malformed JSON-RPC input graceful - #412

Open
chr-hertel wants to merge 3 commits into
mainfrom
fix/malformed-input-hardening
Open

[Server] Handle malformed JSON-RPC input graceful#412
chr-hertel wants to merge 3 commits into
mainfrom
fix/malformed-input-hardening

Conversation

@chr-hertel

@chr-hertel chr-hertel commented Aug 10, 2026

Copy link
Copy Markdown
Member

Malformed input could fail with a PHP TypeError/ValueError instead of an InvalidInputMessageException. Those escape every catch on the way out — MessageFactory, Protocol::processInput(), BaseTransport::handleMessage() and Server::run() — so the peer got a dead process instead of a JSON-RPC error.

  • Protocol::processInput() never lets a throwable escape, reporting anything unexpected as -32603, and guards each message of a batch on its own.
  • The schema hydration methods validate payload types, so type-confused input becomes a descriptive -32600 instead of a PHP error.
  • Unexpected handler exceptions no longer put their message in the -32603 reply, matching what the tool, prompt, resource and completion handlers already do.

Reported by @nickelsec.

@chr-hertel chr-hertel added bug Something isn't working Server Issues & PRs related to the Server component labels Aug 10, 2026
@chr-hertel chr-hertel changed the title Handle malformed JSON-RPC input without crashing the server [Server] Handle malformed JSON-RPC input graceful Aug 10, 2026
@chr-hertel
chr-hertel force-pushed the fix/malformed-input-hardening branch 2 times, most recently from c3fbec1 to 60208a4 Compare August 10, 2026 22:22
@chr-hertel
chr-hertel requested a balanced review from Copilot August 10, 2026 22:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens server-side JSON-RPC processing against malformed payloads and unexpected PHP throwables.

Changes:

  • Adds protocol-level exception containment and generic internal errors.
  • Validates schema payload types during hydration.
  • Expands malformed-input and exception-handling tests.

Reviewed changes

Copilot reviewed 50 out of 50 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/JsonRpc/MessageFactory.php Validates JSON-RPC method types.
src/Server/Protocol.php Contains unexpected processing failures.
src/Schema/Annotations.php Validates annotation payloads.
src/Schema/Content/AudioContent.php Validates audio fields and annotations.
src/Schema/Content/BlobResourceContents.php Validates optional blob metadata.
src/Schema/Content/EmbeddedResource.php Safely hydrates annotations.
src/Schema/Content/PromptMessage.php Validates content types and roles.
src/Schema/Content/SamplingMessage.php Validates content types and roles.
src/Schema/Content/TextContent.php Safely hydrates annotations.
src/Schema/Content/TextResourceContents.php Validates optional text metadata.
src/Schema/Elicitation/ElicitationSchema.php Validates required-property lists.
src/Schema/Extension/Apps/UiResourceContentMeta.php Validates UI resource metadata.
src/Schema/Extension/Apps/UiResourceCsp.php Validates CSP containers.
src/Schema/Extension/Apps/UiToolMeta.php Validates UI tool metadata.
src/Schema/Icon.php Adds safe icon-list hydration.
src/Schema/Implementation.php Validates implementation metadata.
src/Schema/ModelPreferences.php Validates model preferences.
src/Schema/Notification/CancelledNotification.php Validates cancellation reasons.
src/Schema/Notification/LoggingMessageNotification.php Validates logging fields and levels.
src/Schema/Notification/ProgressNotification.php Validates numeric progress fields.
src/Schema/Prompt.php Safely hydrates arguments and icons.
src/Schema/PromptArgument.php Validates optional argument fields.
src/Schema/Request/CompletionCompleteRequest.php Validates completion references.
src/Schema/Request/CreateSamplingMessageRequest.php Validates sampling parameters.
src/Schema/Request/InitializeRequest.php Validates initialization parameters.
src/Schema/Request/ListPromptsRequest.php Validates prompt cursor.
src/Schema/Request/ListResourcesRequest.php Validates resource cursor.
src/Schema/Request/ListResourceTemplatesRequest.php Validates template cursor.
src/Schema/Request/ListToolsRequest.php Validates tool cursor.
src/Schema/Request/SetLogLevelRequest.php Safely validates logging levels.
src/Schema/ResourceDefinition.php Validates resource metadata and icons.
src/Schema/ResourceTemplate.php Validates template metadata.
src/Schema/Result/CallToolResult.php Validates tool result fields.
src/Schema/Result/CompletionCompleteResult.php Validates completion result fields.
src/Schema/Result/CreateSamplingMessageResult.php Safely validates result roles.
src/Schema/Result/ElicitResult.php Safely validates elicitation actions.
src/Schema/Result/GetPromptResult.php Validates prompt result messages.
src/Schema/Result/InitializeResult.php Validates initialization result metadata.
src/Schema/Result/ListPromptsResult.php Validates prompt lists and cursors.
src/Schema/Result/ListResourcesResult.php Validates resource lists and cursors.
src/Schema/Result/ListResourceTemplatesResult.php Validates template lists and cursors.
src/Schema/Result/ListToolsResult.php Validates tool lists and cursors.
src/Schema/Root.php Validates optional root names.
src/Schema/Tool.php Uses safe icon-list hydration.
src/Schema/ToolAnnotations.php Validates tool annotation fields.
tests/Unit/Fixtures/ThrowingRequest.php Provides throwable-producing fixture.
tests/Unit/JsonRpc/MalformedInputTest.php Covers malformed payload hydration.
tests/Unit/JsonRpc/MessageFactoryTest.php Covers invalid method types and batches.
tests/Unit/Schema/Result/ElicitResultTest.php Updates invalid-action expectations.
tests/Unit/Server/ProtocolTest.php Covers containment and message redaction.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Server/Protocol.php
// Last line of defense: a malformed message must never escape as a PHP error and take the
// server process down.
try {
$this->doProcessInput($transport, $input, $sessionId);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking this as known issue

Comment thread src/Server/Protocol.php Outdated
Comment thread src/Server/Protocol.php Outdated
Comment thread src/Schema/Request/CreateSamplingMessageRequest.php Outdated
Comment on lines +66 to +68
if (isset($preferences['hints']) && !\is_array($preferences['hints'])) {
throw new InvalidArgumentException('Invalid "hints" in ModelPreferences data.');
}
@chr-hertel chr-hertel added this to the 0.8.0 milestone Aug 10, 2026
@chr-hertel
chr-hertel force-pushed the fix/malformed-input-hardening branch from 60208a4 to 07c6e0d Compare August 10, 2026 23:50
@chr-hertel
chr-hertel force-pushed the fix/malformed-input-hardening branch from 07c6e0d to e44dcf9 Compare August 10, 2026 23:59
@chr-hertel chr-hertel added the enhancement Request for a new feature that's not currently supported label Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement Request for a new feature that's not currently supported Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants