Skip to content

fix(mcp): a bare 'null' JSON-RPC line must not crash the server - #2511

Merged
namastex888 merged 1 commit into
devfrom
fix/mcp-null-request-crash
Jul 3, 2026
Merged

namastex888 merged 1 commit into
devfrom
fix/mcp-null-request-crash

Conversation

@namastex888

Copy link
Copy Markdown
Contributor

Finding (Gemini review on #2510, HIGH)

src/term-commands/mcp.ts — the newline JSON-RPC loop parses each line with JSON.parse, catching only parse errors. But JSON.parse('null') is valid JSON returning null: req becomes null, dispatch(null) throws accessing null.id (mcp.ts:105), and the catch (e) handler also reads req.id on null → a second, uncaught TypeError → the stdio MCP server crashes on a single null line. (Bare primitives like 5/true reach dispatch harmlessly — only null crashes — but the guard covers all non-objects.)

Fix

After a successful parse, drop any value that isn't a non-null object — it can't be a JSON-RPC request and carries no id to attribute, exactly like an unparseable line:

if (req === null || typeof req !== 'object') return;

Test

New regression drives raw null / 5 / true / "str" lines followed by a valid initialize and asserts the server survives + answers initialize (previously it crashed on the null line). Verified against the built dist/genie.js too.

Gates: bun run check green; typecheck clean; 15 mcp tests pass.

… the server

Gemini PR review (HIGH): JSON.parse('null') is valid JSON returning null, so
dispatch(null) throws on null.id (mcp.ts:105) and the catch handler's own
req.id throws again → uncaught → the stdio server crashes on a single 'null'
line. Guard: after parse, drop any non-object (null/primitive) like an
unparseable line — it carries no id to attribute. Regression test drives raw
null/primitive lines and asserts the server survives + answers initialize.
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5bfa12c7-5e70-49ac-bc33-8862e457dd6f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mcp-null-request-crash

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request adds validation to the MCP server to drop incoming JSON-RPC requests that are null or bare primitives, preventing server crashes. It also introduces a test helper and test cases to verify this behavior. The review feedback suggests extending this validation to explicitly reject arrays (which have a typeof value of 'object') since batch requests are not supported, and updating the test cases to cover this scenario.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/term-commands/mcp.ts
// primitives are valid JSON but carry no id to attribute — drop them like an
// unparseable line. Without this, `dispatch(null)` (and the catch below) throw
// on `null.id`, and the uncaught error crashes the server on a `null` line.
if (req === null || typeof req !== 'object') return;

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.

medium

While typeof req === 'object' correctly filters out primitives and null, it does not filter out arrays (e.g., [] or a JSON-RPC batch request). In JavaScript, typeof [] is 'object'. If an array is passed, it will proceed to dispatch(req), where req.id and req.method will be undefined, causing it to be treated as a notification and silently ignored. Since this server does not support batch requests, we should explicitly reject arrays using Array.isArray(req) to ensure only actual non-null objects are processed.

Suggested change
if (req === null || typeof req !== 'object') return;
if (req === null || typeof req !== 'object' || Array.isArray(req)) return;

test('a bare `null` / primitive line is dropped and does not crash the server', async () => {
// `JSON.parse('null')` is valid JSON but not a JSON-RPC object; without the
// non-object guard, dispatch(null) throws on null.id and the server crashes.
const res = await driveMcpRaw(repo, ['null', '5', 'true', '"str"', JSON.stringify(INIT)]);

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.

medium

Add an empty array [] to the list of raw malformed lines to verify that the server also safely drops arrays without crashing or processing them.

Suggested change
const res = await driveMcpRaw(repo, ['null', '5', 'true', '"str"', JSON.stringify(INIT)]);
const res = await driveMcpRaw(repo, ['null', '5', 'true', '"str"', '[]', JSON.stringify(INIT)]);

@namastex888
namastex888 merged commit c15f803 into dev Jul 3, 2026
11 checks passed
@automagik-genie
automagik-genie deleted the fix/mcp-null-request-crash branch September 25, 2026 04:50
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.

1 participant