mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 16:14:31 +00:00
83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { describe, expect, it } from 'bun:test';
|
|
import { runMcpRequests } from './browser-mcp-test-harness';
|
|
import type { MockPageState } from './browser-mcp-test-harness';
|
|
|
|
describe('ccs-browser MCP server - recording security', () => {
|
|
it('filters sensitive text targets and printable key presses in injected recorder code', () => {
|
|
const source = readFileSync('lib/mcp/ccs-browser-server.cjs', 'utf8');
|
|
const sensitiveAttributePatternMatch = source.match(
|
|
/const sensitiveAttributePattern = \/(.+)\/i;/
|
|
);
|
|
|
|
expect(source).toContain("sensitiveInputTypes = new Set(['password', 'hidden'])");
|
|
expect(source).toContain('sensitiveAutocompleteValues');
|
|
expect(source).toContain('autocompleteTokens.some((token) => sensitiveAutocompleteValues.has(token))');
|
|
expect(source).toContain('isSensitiveTextTarget(target)');
|
|
expect(source).toContain("typeof event.key !== 'string' || event.key.length !== 1");
|
|
expect(sensitiveAttributePatternMatch).not.toBeNull();
|
|
|
|
const sensitiveAttributePattern = new RegExp(sensitiveAttributePatternMatch![1], 'i');
|
|
expect(sensitiveAttributePattern.test('verification_code')).toBe(true);
|
|
expect(sensitiveAttributePattern.test('security-code')).toBe(true);
|
|
expect(sensitiveAttributePattern.test('pin')).toBe(true);
|
|
expect(sensitiveAttributePattern.test('auth_token')).toBe(true);
|
|
expect(sensitiveAttributePattern.test('author')).toBe(false);
|
|
});
|
|
|
|
it('tears down page recording hooks when stopping or clearing', async () => {
|
|
const pages: MockPageState[] = [
|
|
{
|
|
id: 'page-1',
|
|
title: 'Recording Page',
|
|
currentUrl: 'https://example.com/recording',
|
|
recording: {
|
|
events: [{ kind: 'click', selector: '#submit', timestamp: 1710000000000 }],
|
|
},
|
|
},
|
|
];
|
|
|
|
await runMcpRequests(pages, [
|
|
{
|
|
jsonrpc: '2.0',
|
|
id: 1,
|
|
method: 'tools/call',
|
|
params: { name: 'browser_start_recording', arguments: {} },
|
|
},
|
|
{
|
|
jsonrpc: '2.0',
|
|
id: 2,
|
|
method: 'tools/call',
|
|
params: { name: 'browser_stop_recording', arguments: {} },
|
|
},
|
|
{
|
|
jsonrpc: '2.0',
|
|
id: 3,
|
|
method: 'tools/call',
|
|
params: { name: 'browser_clear_recording', arguments: {} },
|
|
},
|
|
]);
|
|
|
|
expect(pages[0].recording?.installed).toBe(false);
|
|
expect(pages[0].recording?.teardownCalls).toBe(1);
|
|
|
|
await runMcpRequests(pages, [
|
|
{
|
|
jsonrpc: '2.0',
|
|
id: 4,
|
|
method: 'tools/call',
|
|
params: { name: 'browser_start_recording', arguments: {} },
|
|
},
|
|
{
|
|
jsonrpc: '2.0',
|
|
id: 5,
|
|
method: 'tools/call',
|
|
params: { name: 'browser_clear_recording', arguments: {} },
|
|
},
|
|
]);
|
|
|
|
expect(pages[0].recording?.installed).toBe(false);
|
|
expect(pages[0].recording?.teardownCalls).toBe(2);
|
|
});
|
|
});
|