142 lines
4.6 KiB
JavaScript
142 lines
4.6 KiB
JavaScript
// tests/detectors.test.js
|
|
|
|
require('../__mocks__/chrome.js');
|
|
const { detectViolations, DETECTOR_NAMES } = require('../lib/detectors.js');
|
|
|
|
describe('Detectors', () => {
|
|
beforeEach(() => {
|
|
global.__chromeStore = {};
|
|
});
|
|
|
|
test('DETECTOR_NAMES has 6 detectors', () => {
|
|
expect(DETECTOR_NAMES).toHaveLength(6);
|
|
expect(DETECTOR_NAMES).toContain('permission_bypass');
|
|
expect(DETECTOR_NAMES).toContain('out_of_scope');
|
|
expect(DETECTOR_NAMES).toContain('self_permissioning');
|
|
expect(DETECTOR_NAMES).toContain('disallowed_tools');
|
|
expect(DETECTOR_NAMES).toContain('redundant_operations');
|
|
expect(DETECTOR_NAMES).toContain('off_task');
|
|
});
|
|
|
|
test('detects permission bypass for disallowed domain', async () => {
|
|
const event = {
|
|
id: 'evt-1',
|
|
type: 'api_call',
|
|
tool: 'fetch',
|
|
target: 'https://malicious.com/api',
|
|
url: 'https://claude.ai/chat',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
const policy = {
|
|
rules: [
|
|
{ id: 'rule_allowed_domains', type: 'allowed_domains', enabled: true, params: { domains: ['github.com', 'claude.ai'] } }
|
|
]
|
|
};
|
|
const violations = await detectViolations(event, policy);
|
|
const bypass = violations.find(v => v.detector === 'permission_bypass');
|
|
expect(bypass).toBeDefined();
|
|
expect(bypass.severity).toBe('high');
|
|
expect(bypass.message).toContain('malicious.com');
|
|
});
|
|
|
|
test('allows permitted domain', async () => {
|
|
const event = {
|
|
id: 'evt-2',
|
|
type: 'api_call',
|
|
tool: 'fetch',
|
|
target: 'https://github.com/api',
|
|
url: 'https://claude.ai/chat',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
const policy = {
|
|
rules: [
|
|
{ id: 'rule_allowed_domains', type: 'allowed_domains', enabled: true, params: { domains: ['github.com'] } }
|
|
]
|
|
};
|
|
const violations = await detectViolations(event, policy);
|
|
const bypass = violations.find(v => v.detector === 'permission_bypass');
|
|
expect(bypass).toBeUndefined();
|
|
});
|
|
|
|
test('detects disallowed tools', async () => {
|
|
const event = {
|
|
id: 'evt-3',
|
|
type: 'tool_use',
|
|
tool: 'eval',
|
|
target: 'some-script.js',
|
|
url: 'https://claude.ai/chat',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
const policy = {
|
|
rules: [
|
|
{ id: 'rule_disallowed_tools', type: 'disallowed_tools', enabled: true, params: { tools: ['eval', 'exec'] } }
|
|
]
|
|
};
|
|
const violations = await detectViolations(event, policy);
|
|
const disallowed = violations.find(v => v.detector === 'disallowed_tools');
|
|
expect(disallowed).toBeDefined();
|
|
expect(disallowed.severity).toBe('critical');
|
|
expect(disallowed.message).toContain('eval');
|
|
});
|
|
|
|
test('detects self-permissioning', async () => {
|
|
const event = {
|
|
id: 'evt-4',
|
|
type: 'tool_use',
|
|
tool: 'edit_file',
|
|
target: 'permissions.json',
|
|
context: 'grant admin access control role privilege',
|
|
url: 'https://claude.ai/chat',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
const policy = {
|
|
rules: [
|
|
{ id: 'rule_permission_change', type: 'permission_change', enabled: true, params: {} }
|
|
]
|
|
};
|
|
const violations = await detectViolations(event, policy);
|
|
const perm = violations.find(v => v.detector === 'self_permissioning');
|
|
expect(perm).toBeDefined();
|
|
expect(perm.severity).toBe('critical');
|
|
});
|
|
|
|
test('detects out-of-scope operations', async () => {
|
|
const event = {
|
|
id: 'evt-5',
|
|
type: 'api_call',
|
|
tool: 'delete',
|
|
target: 'https://api.example.com/resource',
|
|
url: 'https://claude.ai/chat',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
const policy = {
|
|
rules: [
|
|
{ id: 'rule_allowed_operations', type: 'allowed_operations', enabled: true, params: { operations: ['read', 'chat'] } }
|
|
]
|
|
};
|
|
const violations = await detectViolations(event, policy);
|
|
const scope = violations.find(v => v.detector === 'out_of_scope');
|
|
expect(scope).toBeDefined();
|
|
expect(scope.severity).toBe('medium');
|
|
});
|
|
|
|
test('no violations for normal activity', async () => {
|
|
const event = {
|
|
id: 'evt-6',
|
|
type: 'chat',
|
|
tool: 'chat',
|
|
target: 'conversation',
|
|
url: 'https://claude.ai/chat',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
const policy = {
|
|
rules: [
|
|
{ id: 'rule_allowed_domains', type: 'allowed_domains', enabled: true, params: { domains: ['claude.ai'] } },
|
|
{ id: 'rule_disallowed_tools', type: 'disallowed_tools', enabled: true, params: { tools: ['eval'] } }
|
|
]
|
|
};
|
|
const violations = await detectViolations(event, policy);
|
|
expect(violations).toHaveLength(0);
|
|
});
|
|
});
|