Skip to content

Commit b229470

Browse files
committed
fix(core): reject invalid JSON-RPC params
1 parent 84bbf38 commit b229470

3 files changed

Lines changed: 86 additions & 3 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@aws-blocks/core": patch
3+
---
4+
5+
Reject primitive and null JSON-RPC params with the standard Invalid Params error.

packages/core/src/rpc.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,65 @@ describe('-32600 Invalid Request error shape', () => {
7171
}
7272
});
7373
});
74+
75+
describe('-32602 Invalid Params validation', () => {
76+
it('accepts positional array params', () => {
77+
const result = parseRpcRequest(JSON.stringify({
78+
jsonrpc: '2.0',
79+
method: 'api.echo',
80+
params: ['hello', 42],
81+
id: 1,
82+
}));
83+
84+
assert.strictEqual(result.ok, true);
85+
if (result.ok) {
86+
assert.deepStrictEqual(result.request.args, ['hello', 42]);
87+
}
88+
});
89+
90+
it('accepts named object params using their value order', () => {
91+
const result = parseRpcRequest(JSON.stringify({
92+
jsonrpc: '2.0',
93+
method: 'api.echo',
94+
params: { message: 'hello', count: 42 },
95+
id: 2,
96+
}));
97+
98+
assert.strictEqual(result.ok, true);
99+
if (result.ok) {
100+
assert.deepStrictEqual(result.request.args, ['hello', 42]);
101+
}
102+
});
103+
104+
it('treats omitted params as no arguments', () => {
105+
const result = parseRpcRequest(JSON.stringify({
106+
jsonrpc: '2.0',
107+
method: 'api.ping',
108+
id: 3,
109+
}));
110+
111+
assert.strictEqual(result.ok, true);
112+
if (result.ok) {
113+
assert.deepStrictEqual(result.request.args, []);
114+
}
115+
});
116+
117+
for (const params of ['abc', 42, true, null]) {
118+
it(`rejects ${JSON.stringify(params)} params`, () => {
119+
const result = parseRpcRequest(JSON.stringify({
120+
jsonrpc: '2.0',
121+
method: 'api.echo',
122+
params,
123+
id: 'request-1',
124+
}));
125+
126+
assert.strictEqual(result.ok, false);
127+
if (!result.ok) {
128+
const response = JSON.parse(result.response);
129+
assert.strictEqual(response.error.code, RpcErrorCode.InvalidParams);
130+
assert.strictEqual(response.error.data.name, 'InvalidParams');
131+
assert.strictEqual(response.id, 'request-1');
132+
}
133+
});
134+
}
135+
});

packages/core/src/rpc.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,31 @@ export function parseRpcRequest(bodyText: string): RpcParseResult {
118118
};
119119
}
120120

121+
const hasParams = Object.hasOwn(parsed, 'params');
122+
if (hasParams && (parsed.params === null || typeof parsed.params !== 'object')) {
123+
return {
124+
ok: false,
125+
response: errorResponse(
126+
RpcErrorCode.InvalidParams,
127+
'Invalid params: expected an array or object',
128+
id,
129+
{ name: 'InvalidParams' },
130+
),
131+
};
132+
}
133+
134+
let args: unknown[] = [];
135+
if (hasParams) {
136+
args = Array.isArray(parsed.params) ? parsed.params : Object.values(parsed.params);
137+
}
138+
121139
return {
122140
ok: true,
123141
request: {
124142
apiNamespace: parsed.method.substring(0, dotIndex),
125143
method: parsed.method.substring(dotIndex + 1),
126144
// JSON-RPC 2.0 §4.2: params may be an array (positional) or object (named).
127-
args: Array.isArray(parsed.params)
128-
? parsed.params
129-
: Object.values(parsed.params ?? {}),
145+
args,
130146
id,
131147
},
132148
};

0 commit comments

Comments
 (0)