feat(security): grow Yerin's toolset (pending_review, resource_exposure, token_audit)
Three more read-only tools on securityRegistry: - pending_review: agent-proposed changes awaiting approval (injection surface) - resource_exposure: host/url/status attack-surface inventory (resources.listExposure, scalar cols only — no monitoring/metadata/credentials) - token_audit: token label/last_used/revoked, never the hash Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { createRegistry } from '../../registry.js';
|
||||
import { auditLogTool } from './audit_log.js';
|
||||
import { agentInventoryTool } from './agent_inventory.js';
|
||||
import { pendingReviewTool } from './pending_review.js';
|
||||
import { resourceExposureTool } from './resource_exposure.js';
|
||||
import { tokenAuditTool } from './token_audit.js';
|
||||
|
||||
// Yerin's security toolset — read-only observability, kept in its own registry
|
||||
// so the security agent gets security tools (not Dross's propose_change). A
|
||||
@@ -9,3 +12,6 @@ import { agentInventoryTool } from './agent_inventory.js';
|
||||
export const securityRegistry = createRegistry();
|
||||
securityRegistry.registerTool(auditLogTool);
|
||||
securityRegistry.registerTool(agentInventoryTool);
|
||||
securityRegistry.registerTool(pendingReviewTool);
|
||||
securityRegistry.registerTool(resourceExposureTool);
|
||||
securityRegistry.registerTool(tokenAuditTool);
|
||||
|
||||
20
lib/ai/agent/tools/security/pending_review.js
Normal file
20
lib/ai/agent/tools/security/pending_review.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as pendingChanges from '../../../../db/repos/pending_changes.js';
|
||||
|
||||
// The queue of agent-proposed mutations awaiting owner approval. This is exactly
|
||||
// where a prompt-injected or misbehaving agent's intent surfaces, so it's a
|
||||
// primary security-review surface.
|
||||
export const pendingReviewTool = {
|
||||
name: 'pending_review',
|
||||
description: 'List pending (unapproved) agent-proposed changes awaiting owner approval — the queue where a misbehaving or injected agent\'s intent shows up. Review these for anything unexpected.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
limit: { type: 'integer', description: 'max rows (default 50, max 200)' }
|
||||
}
|
||||
},
|
||||
async handler({ limit } = {}, _ctx) {
|
||||
const capped = Math.min(Math.max(Number(limit) || 50, 1), 200);
|
||||
const pending = await pendingChanges.listPending({ limit: capped });
|
||||
return { pending };
|
||||
}
|
||||
};
|
||||
14
lib/ai/agent/tools/security/resource_exposure.js
Normal file
14
lib/ai/agent/tools/security/resource_exposure.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as resources from '../../../../db/repos/resources.js';
|
||||
|
||||
// Attack-surface inventory: every resource's host/url/status across all spaces.
|
||||
// Backed by resources.listExposure (scalar columns only — no monitoring/metadata
|
||||
// JSON, no credentials).
|
||||
export const resourceExposureTool = {
|
||||
name: 'resource_exposure',
|
||||
description: 'Inventory of all resources (services/hosts) with their host, url and status — the reachable attack surface. Use to spot exposed or unexpected services. Never includes secrets or monitoring config.',
|
||||
input_schema: { type: 'object', properties: {} },
|
||||
async handler(_args, _ctx) {
|
||||
const resourceList = await resources.listExposure();
|
||||
return { resources: resourceList };
|
||||
}
|
||||
};
|
||||
13
lib/ai/agent/tools/security/token_audit.js
Normal file
13
lib/ai/agent/tools/security/token_audit.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as agents from '../../../../db/repos/agents.js';
|
||||
|
||||
// Agent credential hygiene: which tokens exist, when last used, whether revoked.
|
||||
// Backed by agents.listTokenMeta — token_hash is never selected.
|
||||
export const tokenAuditTool = {
|
||||
name: 'token_audit',
|
||||
description: 'List agent API tokens with label, last_used and revoked status (never the secret) so you can spot stale, unused, or unexpected credentials. Recommend revoking anything dormant.',
|
||||
input_schema: { type: 'object', properties: {} },
|
||||
async handler(_args, _ctx) {
|
||||
const tokens = await agents.listTokenMeta();
|
||||
return { tokens };
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user