Agent Police Department v1.0.0 MVP
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
// 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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user