mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 14:16:43 +00:00
fix(browser): cap click and key repeat counts in MCP (#1367)
* fix(browser): cap click and key repeat counts in MCP * style: apply prettier formatting
This commit is contained in:
@@ -159,6 +159,8 @@ const DEFAULT_WAIT_TIMEOUT_MS = 2000;
|
||||
const DEFAULT_WAIT_POLL_INTERVAL_MS = 100;
|
||||
const DEFAULT_DRAG_STEPS = 5;
|
||||
const MAX_POINTER_ACTIONS = 25;
|
||||
const MAX_CLICK_COUNT = 25;
|
||||
const MAX_KEY_REPEAT = 25;
|
||||
const SESSION_START_SETTLE_WINDOW_MS = 250;
|
||||
const MAX_ARTIFACT_FILE_BYTES = 5 * 1024 * 1024;
|
||||
const MAX_LOCAL_TRANSFER_FILE_BYTES = 10 * 1024 * 1024;
|
||||
@@ -454,6 +456,7 @@ function getTools() {
|
||||
clickCount: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: MAX_CLICK_COUNT,
|
||||
description: 'Optional click count. Defaults to 1.',
|
||||
},
|
||||
},
|
||||
@@ -519,6 +522,7 @@ function getTools() {
|
||||
repeat: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: MAX_KEY_REPEAT,
|
||||
description: 'Optional repeat count. Defaults to 1.',
|
||||
},
|
||||
},
|
||||
@@ -2305,10 +2309,13 @@ function requirePositiveIntegerOrDefault(value, label, fallback) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function requirePositiveInteger(value, label) {
|
||||
function requirePositiveInteger(value, label, maximum = undefined) {
|
||||
if (!Number.isInteger(value) || value <= 0) {
|
||||
throw new Error(`${label} must be a positive integer`);
|
||||
}
|
||||
if (maximum !== undefined && value > maximum) {
|
||||
throw new Error(`${label} must be less than or equal to ${maximum}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -3555,7 +3562,7 @@ async function handleClick(toolArgs) {
|
||||
const clickCount =
|
||||
toolArgs.clickCount === undefined
|
||||
? 1
|
||||
: requirePositiveInteger(toolArgs.clickCount, 'clickCount');
|
||||
: requirePositiveInteger(toolArgs.clickCount, 'clickCount', MAX_CLICK_COUNT);
|
||||
|
||||
const expression = `(() => {
|
||||
const selector = JSON.parse(${JSON.stringify(JSON.stringify(selector))});
|
||||
@@ -3805,7 +3812,9 @@ async function handlePressKey(toolArgs) {
|
||||
'Shift',
|
||||
]);
|
||||
const repeat =
|
||||
toolArgs.repeat === undefined ? 1 : requirePositiveInteger(toolArgs.repeat, 'repeat');
|
||||
toolArgs.repeat === undefined
|
||||
? 1
|
||||
: requirePositiveInteger(toolArgs.repeat, 'repeat', MAX_KEY_REPEAT);
|
||||
const modifierMask =
|
||||
(modifiers.includes('Alt') ? 1 : 0) |
|
||||
(modifiers.includes('Control') ? 2 : 0) |
|
||||
|
||||
@@ -722,6 +722,47 @@ describe('ccs-browser MCP server - navigation and query', () => {
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('rejects excessive clickCount and repeat values', async () => {
|
||||
const responses = await runMcpRequests(
|
||||
[{ id: 'page-1', title: 'Limits Page', currentUrl: 'https://example.com/' }],
|
||||
[
|
||||
{
|
||||
jsonrpc: '2.0',
|
||||
id: 713,
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'browser_click',
|
||||
arguments: {
|
||||
selector: '#submit',
|
||||
clickCount: 26,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
jsonrpc: '2.0',
|
||||
id: 714,
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'browser_press_key',
|
||||
arguments: {
|
||||
key: 'k',
|
||||
repeat: 26,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
const clickResponse = responses.find((message) => message.id === 713);
|
||||
expect((clickResponse?.result as { isError?: boolean }).isError).toBe(true);
|
||||
expect(getResponseText(clickResponse)).toContain('clickCount must be less than or equal to 25');
|
||||
|
||||
const keyResponse = responses.find((message) => message.id === 714);
|
||||
expect((keyResponse?.result as { isError?: boolean }).isError).toBe(true);
|
||||
expect(getResponseText(keyResponse)).toContain('repeat must be less than or equal to 25');
|
||||
});
|
||||
|
||||
it('scrolls an element into view with browser_scroll', async () => {
|
||||
const responses = await runMcpRequests(
|
||||
[
|
||||
|
||||
@@ -79,11 +79,17 @@ describe('ccs-browser MCP server - session and interception', () => {
|
||||
expect(clickTool?.inputSchema?.properties?.clickCount).toMatchObject({
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 25,
|
||||
});
|
||||
|
||||
const keyTool = tools.find((tool) => tool.name === 'browser_press_key');
|
||||
expect(keyTool?.inputSchema?.properties?.key).toMatchObject({ type: 'string' });
|
||||
expect(keyTool?.inputSchema?.properties?.modifiers).toMatchObject({ type: 'array' });
|
||||
expect(keyTool?.inputSchema?.properties?.repeat).toMatchObject({
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 25,
|
||||
});
|
||||
|
||||
const scrollTool = tools.find((tool) => tool.name === 'browser_scroll');
|
||||
expect(scrollTool?.inputSchema?.properties?.deltaX).toMatchObject({ type: 'number' });
|
||||
|
||||
Reference in New Issue
Block a user