Skip to content

fix(core): reject invalid JSON-RPC params#181

Open
ikenyal wants to merge 3 commits into
aws-devtools-labs:mainfrom
ikenyal:fix/json-rpc-invalid-params
Open

fix(core): reject invalid JSON-RPC params#181
ikenyal wants to merge 3 commits into
aws-devtools-labs:mainfrom
ikenyal:fix/json-rpc-invalid-params

Conversation

@ikenyal

@ikenyal ikenyal commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Problem

JSON-RPC requests with primitive or null params are currently accepted instead of returning the standard -32602 Invalid Params error. The Object.values(parsed.params ?? {}) fallback turns strings into character arguments and numbers, booleans, and null into an empty argument list, so malformed requests can reach application methods with unexpected arguments.

Closes #179.

Changes

  • Validate a present params property before constructing method arguments.
  • Return RpcErrorCode.InvalidParams with data.name: "InvalidParams" for primitive and null values while preserving the request id.
  • Preserve the existing behavior for positional arrays, named objects, and omitted params.
  • Add focused unit coverage for all accepted and rejected shapes.
  • Add a patch changeset for @aws-blocks/core.

Validation

  • npm ci
  • npm run build:packages
  • npm run build -w @aws-blocks/core
  • node --test --test-concurrency=1 dist/*.test.js dist/**/*.test.js from packages/core (588 passed, 0 failed)
  • npm run lint
  • npm run lint:deps
  • npm run check:exports-consistency
  • npm run check:api
  • npx @changesets/cli status --since=origin/main
  • npx tsx scripts/verify-changeset-coverage.ts
  • git diff --cached --check

Checklist

  • PR description included
  • Tests are changed or added
  • Relevant documentation is changed or added (not applicable; this enforces the JSON-RPC 2.0 input shape and does not change the supported array/object/omitted forms)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@ikenyal
ikenyal requested a review from a team as a code owner July 10, 2026 00:16
Comment thread packages/core/src/rpc.ts Outdated
request: {
apiNamespace: parsed.method.substring(0, dotIndex),
method: parsed.method.substring(dotIndex + 1),
// JSON-RPC 2.0 §4.2: params may be an array (positional) or object (named).

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.

The comment only mentions array (positional) and object (named), but after the refactor args is also [] when params is omitted entirely. Suggest updating so the third path is documented:

Suggested change
// JSON-RPC 2.0 §4.2: params may be an array (positional) or object (named).
// JSON-RPC 2.0 §4.2: params may be array (positional), object (named), or omitted (empty).

Comment thread packages/core/src/rpc.test.ts Outdated
}
});

for (const params of ['abc', 42, true, null]) {

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.

false is the only boolean not covered here — it's rejected by the same typeof !== 'object' guard but is absent from the set. Adding it completes coverage of all four primitive types (string, number, boolean, null):

Suggested change
for (const params of ['abc', 42, true, null]) {
for (const params of ['abc', 42, true, false, null]) {

const response = JSON.parse(result.response);
assert.strictEqual(response.error.code, RpcErrorCode.InvalidParams);
assert.strictEqual(response.error.data.name, 'InvalidParams');
assert.strictEqual(response.id, 'request-1');

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.

These tests assert error.code and error.data.name but not error.message. The existing -32600 tests assert message content; the user-facing -32602 message could regress silently. One assertion would close the gap:

assert.ok(response.error.message.includes('expected an array or object'));

Comment thread packages/core/src/rpc.test.ts Outdated
}
});

it('accepts named object params using their value order', () => {

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.

nit: "using their value order" leans on an Object.values() implementation detail. JSON-RPC doesn't guarantee param ordering for named objects, so a neutral name like 'accepts named object params' avoids setting a false reader expectation.

ahmedhamouda78
ahmedhamouda78 previously approved these changes Jul 10, 2026

@ahmedhamouda78 ahmedhamouda78 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.

Approving. This is a clean, spec-correct fix for #179 — the -32602 Invalid Params guard is exactly right: Object.hasOwn distinguishes absent from present params, and the params === null || typeof params !== 'object' check correctly covers all four primitive types (the typeof null === 'object' trap is handled by the explicit === null arm). Preserving the request id in the error response is spec-required and done correctly. Extracting let args from the inline ternary is a nice readability win, and patch is the right changeset level.

Left a few non-blocking notes: add false to the rejection test loop for full boolean coverage, assert error.message in one -32602 case to guard against silent message regressions, refresh the args comment at rpc.ts:130 to mention the omitted-params path, and a naming nit on the named-object test. None block merge.

@ikenyal

ikenyal commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

@ahmedhamouda78
Thanks for the review. I’ve incorporated all four suggestions and rebased the branch onto the latest main. All relevant tests and validation checks pass. This PR is ready for re-review.

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.

JSON-RPC parser accepts primitive params instead of returning InvalidParams

2 participants