@kernel.chat/kbot 3.20.1 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +33 -0
- package/dist/agent.js.map +1 -1
- package/dist/cli.js +141 -1
- package/dist/cli.js.map +1 -1
- package/dist/discovery.d.ts +58 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +364 -0
- package/dist/discovery.js.map +1 -0
- package/dist/privacy-router.d.ts +48 -0
- package/dist/privacy-router.d.ts.map +1 -0
- package/dist/privacy-router.js +247 -0
- package/dist/privacy-router.js.map +1 -0
- package/dist/sandbox-policy.d.ts +47 -0
- package/dist/sandbox-policy.d.ts.map +1 -0
- package/dist/sandbox-policy.js +257 -0
- package/dist/sandbox-policy.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// kbot Privacy Router — local-first, cloud only when explicitly allowed
|
|
2
|
+
//
|
|
3
|
+
// Inspired by NemoClaw's privacy router architecture.
|
|
4
|
+
// All queries go through this router BEFORE hitting any provider.
|
|
5
|
+
//
|
|
6
|
+
// Rules:
|
|
7
|
+
// 1. Default: everything runs local (Ollama)
|
|
8
|
+
// 2. Sensitive content (secrets, personal data, proprietary code) → ALWAYS local
|
|
9
|
+
// 3. Cloud only when: user explicitly allows via policy, AND content passes privacy check
|
|
10
|
+
// 4. Policy defined in ~/.kbot/policies/privacy.yaml
|
|
11
|
+
//
|
|
12
|
+
// This is the layer between the user's prompt and the provider.
|
|
13
|
+
// It never sends sensitive data to cloud APIs unless the user says so.
|
|
14
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
// ── Paths ──
|
|
18
|
+
const POLICY_DIR = join(homedir(), '.kbot', 'policies');
|
|
19
|
+
const PRIVACY_POLICY_FILE = join(POLICY_DIR, 'privacy.yaml');
|
|
20
|
+
const AUDIT_LOG_FILE = join(POLICY_DIR, 'privacy-audit.log');
|
|
21
|
+
// ── Default Policy ──
|
|
22
|
+
const DEFAULT_POLICY = {
|
|
23
|
+
defaultLevel: 'local-preferred',
|
|
24
|
+
sensitivePatterns: [
|
|
25
|
+
// Secrets & credentials
|
|
26
|
+
'api[_-]?key', 'secret[_-]?key', 'password', 'token',
|
|
27
|
+
'bearer\\s+[a-zA-Z0-9]', 'sk-[a-zA-Z0-9]', 'ghp_[a-zA-Z0-9]',
|
|
28
|
+
'aws[_-]?access', 'aws[_-]?secret',
|
|
29
|
+
// Personal data
|
|
30
|
+
'social\\s*security', 'ssn', 'credit\\s*card', '\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}\\b',
|
|
31
|
+
'date\\s*of\\s*birth', 'passport',
|
|
32
|
+
// Proprietary markers
|
|
33
|
+
'confidential', 'proprietary', 'internal\\s*only', 'do\\s*not\\s*share',
|
|
34
|
+
// .env file contents
|
|
35
|
+
'SUPABASE_SERVICE', 'DATABASE_URL', 'PRIVATE_KEY',
|
|
36
|
+
],
|
|
37
|
+
allowedCloudHosts: [
|
|
38
|
+
'api.anthropic.com',
|
|
39
|
+
'api.openai.com',
|
|
40
|
+
'generativelanguage.googleapis.com',
|
|
41
|
+
'api.groq.com',
|
|
42
|
+
'api.deepseek.com',
|
|
43
|
+
],
|
|
44
|
+
privateFilePaths: [
|
|
45
|
+
'.env', '.env.local', '.env.production',
|
|
46
|
+
'*.pem', '*.key', '*.p12',
|
|
47
|
+
'**/credentials*', '**/secrets*',
|
|
48
|
+
'~/.ssh/*', '~/.aws/*',
|
|
49
|
+
],
|
|
50
|
+
auditLog: true,
|
|
51
|
+
};
|
|
52
|
+
// ── Policy Loading ──
|
|
53
|
+
function ensureDir() {
|
|
54
|
+
if (!existsSync(POLICY_DIR))
|
|
55
|
+
mkdirSync(POLICY_DIR, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
/** Load privacy policy from YAML-like config, or return defaults */
|
|
58
|
+
export function loadPrivacyPolicy() {
|
|
59
|
+
if (!existsSync(PRIVACY_POLICY_FILE))
|
|
60
|
+
return DEFAULT_POLICY;
|
|
61
|
+
try {
|
|
62
|
+
const content = readFileSync(PRIVACY_POLICY_FILE, 'utf8');
|
|
63
|
+
// Simple YAML-like parser (no dependency needed)
|
|
64
|
+
const policy = { ...DEFAULT_POLICY };
|
|
65
|
+
const levelMatch = content.match(/defaultLevel:\s*(.+)/);
|
|
66
|
+
if (levelMatch)
|
|
67
|
+
policy.defaultLevel = levelMatch[1].trim();
|
|
68
|
+
const auditMatch = content.match(/auditLog:\s*(true|false)/);
|
|
69
|
+
if (auditMatch)
|
|
70
|
+
policy.auditLog = auditMatch[1] === 'true';
|
|
71
|
+
// Parse sensitive patterns list
|
|
72
|
+
const sensSection = content.match(/sensitivePatterns:\n((?:\s+-\s+.+\n?)+)/);
|
|
73
|
+
if (sensSection) {
|
|
74
|
+
policy.sensitivePatterns = sensSection[1]
|
|
75
|
+
.split('\n')
|
|
76
|
+
.map(l => l.replace(/^\s+-\s+/, '').trim())
|
|
77
|
+
.filter(Boolean);
|
|
78
|
+
}
|
|
79
|
+
// Parse allowed cloud hosts
|
|
80
|
+
const hostSection = content.match(/allowedCloudHosts:\n((?:\s+-\s+.+\n?)+)/);
|
|
81
|
+
if (hostSection) {
|
|
82
|
+
policy.allowedCloudHosts = hostSection[1]
|
|
83
|
+
.split('\n')
|
|
84
|
+
.map(l => l.replace(/^\s+-\s+/, '').trim())
|
|
85
|
+
.filter(Boolean);
|
|
86
|
+
}
|
|
87
|
+
// Parse private file paths
|
|
88
|
+
const fileSection = content.match(/privateFilePaths:\n((?:\s+-\s+.+\n?)+)/);
|
|
89
|
+
if (fileSection) {
|
|
90
|
+
policy.privateFilePaths = fileSection[1]
|
|
91
|
+
.split('\n')
|
|
92
|
+
.map(l => l.replace(/^\s+-\s+/, '').trim())
|
|
93
|
+
.filter(Boolean);
|
|
94
|
+
}
|
|
95
|
+
return policy;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return DEFAULT_POLICY;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Write the default policy file so users can customize it */
|
|
102
|
+
export function writeDefaultPolicy() {
|
|
103
|
+
ensureDir();
|
|
104
|
+
const yaml = `# kbot Privacy Policy
|
|
105
|
+
# Controls when data can be sent to cloud AI providers vs kept local.
|
|
106
|
+
# Edit this file to customize your privacy preferences.
|
|
107
|
+
|
|
108
|
+
# Options: local-only, local-preferred, cloud-allowed
|
|
109
|
+
defaultLevel: local-preferred
|
|
110
|
+
|
|
111
|
+
# Log all routing decisions to privacy-audit.log
|
|
112
|
+
auditLog: true
|
|
113
|
+
|
|
114
|
+
# Patterns that ALWAYS force local inference (regex)
|
|
115
|
+
# If any of these match the prompt or tool args, cloud is blocked.
|
|
116
|
+
sensitivePatterns:
|
|
117
|
+
- api[_-]?key
|
|
118
|
+
- secret[_-]?key
|
|
119
|
+
- password
|
|
120
|
+
- token
|
|
121
|
+
- bearer\\s+[a-zA-Z0-9]
|
|
122
|
+
- sk-[a-zA-Z0-9]
|
|
123
|
+
- ghp_[a-zA-Z0-9]
|
|
124
|
+
- aws[_-]?access
|
|
125
|
+
- social\\s*security
|
|
126
|
+
- credit\\s*card
|
|
127
|
+
- confidential
|
|
128
|
+
- proprietary
|
|
129
|
+
- SUPABASE_SERVICE
|
|
130
|
+
- DATABASE_URL
|
|
131
|
+
- PRIVATE_KEY
|
|
132
|
+
|
|
133
|
+
# Cloud API hosts allowed (only used when defaultLevel is cloud-allowed)
|
|
134
|
+
allowedCloudHosts:
|
|
135
|
+
- api.anthropic.com
|
|
136
|
+
- api.openai.com
|
|
137
|
+
- generativelanguage.googleapis.com
|
|
138
|
+
- api.groq.com
|
|
139
|
+
- api.deepseek.com
|
|
140
|
+
|
|
141
|
+
# File paths that are always treated as private (glob patterns)
|
|
142
|
+
privateFilePaths:
|
|
143
|
+
- .env
|
|
144
|
+
- .env.local
|
|
145
|
+
- .env.production
|
|
146
|
+
- "*.pem"
|
|
147
|
+
- "*.key"
|
|
148
|
+
- "**/credentials*"
|
|
149
|
+
- "**/secrets*"
|
|
150
|
+
`;
|
|
151
|
+
writeFileSync(PRIVACY_POLICY_FILE, yaml);
|
|
152
|
+
}
|
|
153
|
+
// ── Sensitive Content Detection ──
|
|
154
|
+
/** Check if content contains sensitive patterns */
|
|
155
|
+
export function detectSensitiveContent(content, policy) {
|
|
156
|
+
const matches = [];
|
|
157
|
+
for (const pattern of policy.sensitivePatterns) {
|
|
158
|
+
try {
|
|
159
|
+
const regex = new RegExp(pattern, 'i');
|
|
160
|
+
if (regex.test(content)) {
|
|
161
|
+
matches.push(pattern);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch { /* invalid regex — skip */ }
|
|
165
|
+
}
|
|
166
|
+
return { sensitive: matches.length > 0, matches };
|
|
167
|
+
}
|
|
168
|
+
/** Check if a file path is private */
|
|
169
|
+
export function isPrivateFilePath(filePath, policy) {
|
|
170
|
+
const normalized = filePath.toLowerCase();
|
|
171
|
+
for (const pattern of policy.privateFilePaths) {
|
|
172
|
+
const p = pattern.toLowerCase();
|
|
173
|
+
if (p.startsWith('**/')) {
|
|
174
|
+
if (normalized.includes(p.slice(3)))
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
else if (p.startsWith('*.')) {
|
|
178
|
+
if (normalized.endsWith(p.slice(1)))
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
if (normalized.endsWith(p) || normalized.includes(`/${p}`))
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
// ── Core: Route Decision ──
|
|
189
|
+
/**
|
|
190
|
+
* Decide whether a prompt/tool call should go to local or cloud.
|
|
191
|
+
* This is called BEFORE every inference request.
|
|
192
|
+
*/
|
|
193
|
+
export function routeForPrivacy(content, policy, options) {
|
|
194
|
+
const p = policy || loadPrivacyPolicy();
|
|
195
|
+
// Force overrides
|
|
196
|
+
if (options?.forceLocal) {
|
|
197
|
+
return { target: 'local', reason: 'Forced local by flag', sensitiveDetected: false, matchedPatterns: [] };
|
|
198
|
+
}
|
|
199
|
+
// Local-only mode — never send anything to cloud
|
|
200
|
+
if (p.defaultLevel === 'local-only') {
|
|
201
|
+
return { target: 'local', reason: 'Policy: local-only mode', sensitiveDetected: false, matchedPatterns: [] };
|
|
202
|
+
}
|
|
203
|
+
// Check for sensitive content
|
|
204
|
+
const check = detectSensitiveContent(content, p);
|
|
205
|
+
if (check.sensitive) {
|
|
206
|
+
return {
|
|
207
|
+
target: 'local',
|
|
208
|
+
reason: `Sensitive content detected: ${check.matches.join(', ')}`,
|
|
209
|
+
sensitiveDetected: true,
|
|
210
|
+
matchedPatterns: check.matches,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
// Check file paths
|
|
214
|
+
if (options?.filePaths) {
|
|
215
|
+
for (const fp of options.filePaths) {
|
|
216
|
+
if (isPrivateFilePath(fp, p)) {
|
|
217
|
+
return {
|
|
218
|
+
target: 'local',
|
|
219
|
+
reason: `Private file path: ${fp}`,
|
|
220
|
+
sensitiveDetected: true,
|
|
221
|
+
matchedPatterns: [fp],
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Cloud-allowed mode — cloud is ok if content passes
|
|
227
|
+
if (p.defaultLevel === 'cloud-allowed' || options?.forceCloud) {
|
|
228
|
+
return { target: 'cloud', reason: 'Content passed privacy check', sensitiveDetected: false, matchedPatterns: [] };
|
|
229
|
+
}
|
|
230
|
+
// Local-preferred — use local unless local is unavailable
|
|
231
|
+
return { target: 'local', reason: 'Policy: local-preferred', sensitiveDetected: false, matchedPatterns: [] };
|
|
232
|
+
}
|
|
233
|
+
// ── Audit Logging ──
|
|
234
|
+
export function logRoutingDecision(decision, prompt) {
|
|
235
|
+
const policy = loadPrivacyPolicy();
|
|
236
|
+
if (!policy.auditLog)
|
|
237
|
+
return;
|
|
238
|
+
ensureDir();
|
|
239
|
+
const entry = `[${new Date().toISOString()}] ${decision.target.toUpperCase()} | ${decision.reason} | prompt: ${prompt.slice(0, 80).replace(/\n/g, ' ')}${decision.matchedPatterns.length > 0 ? ` | matches: ${decision.matchedPatterns.join(',')}` : ''}\n`;
|
|
240
|
+
try {
|
|
241
|
+
const { appendFileSync } = require('node:fs');
|
|
242
|
+
appendFileSync(AUDIT_LOG_FILE, entry);
|
|
243
|
+
}
|
|
244
|
+
catch { /* non-critical */ }
|
|
245
|
+
}
|
|
246
|
+
export { DEFAULT_POLICY, PRIVACY_POLICY_FILE };
|
|
247
|
+
//# sourceMappingURL=privacy-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privacy-router.js","sourceRoot":"","sources":["../src/privacy-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface AgentPolicy {
|
|
2
|
+
/** Agent ID this policy applies to */
|
|
3
|
+
agentId: string;
|
|
4
|
+
/** Tools this agent is allowed to use (empty = all allowed) */
|
|
5
|
+
allowedTools: string[];
|
|
6
|
+
/** Tools explicitly blocked */
|
|
7
|
+
blockedTools: string[];
|
|
8
|
+
/** File paths the agent can access (glob patterns) */
|
|
9
|
+
allowedPaths: string[];
|
|
10
|
+
/** File paths the agent cannot access */
|
|
11
|
+
blockedPaths: string[];
|
|
12
|
+
/** Max execution time in seconds per tool call */
|
|
13
|
+
maxExecutionTime: number;
|
|
14
|
+
/** Whether the agent can make network requests */
|
|
15
|
+
networkAccess: boolean;
|
|
16
|
+
/** Whether the agent can execute shell commands */
|
|
17
|
+
shellAccess: boolean;
|
|
18
|
+
/** Max file size the agent can write (bytes) */
|
|
19
|
+
maxFileSize: number;
|
|
20
|
+
/** Whether the agent can install packages */
|
|
21
|
+
canInstallPackages: boolean;
|
|
22
|
+
}
|
|
23
|
+
declare const DEFAULT_POLICY: Omit<AgentPolicy, 'agentId'>;
|
|
24
|
+
/** Strict policy for untrusted/new agents */
|
|
25
|
+
declare const STRICT_POLICY: Omit<AgentPolicy, 'agentId'>;
|
|
26
|
+
/** Built-in policies for known agents */
|
|
27
|
+
declare const BUILTIN_POLICIES: Record<string, Partial<AgentPolicy>>;
|
|
28
|
+
/** Load a specific agent's policy from file, falling back to builtins then defaults */
|
|
29
|
+
export declare function loadAgentPolicy(agentId: string): AgentPolicy;
|
|
30
|
+
export interface PolicyCheckResult {
|
|
31
|
+
allowed: boolean;
|
|
32
|
+
reason?: string;
|
|
33
|
+
}
|
|
34
|
+
/** Check if an agent is allowed to use a specific tool */
|
|
35
|
+
export declare function checkToolAccess(agentId: string, toolName: string, policy?: AgentPolicy): PolicyCheckResult;
|
|
36
|
+
/** Check if an agent can access a file path */
|
|
37
|
+
export declare function checkPathAccess(agentId: string, filePath: string, policy?: AgentPolicy): PolicyCheckResult;
|
|
38
|
+
/** List all agent policies (builtin + user-defined) */
|
|
39
|
+
export declare function listPolicies(): Array<{
|
|
40
|
+
agentId: string;
|
|
41
|
+
source: 'builtin' | 'user';
|
|
42
|
+
policy: AgentPolicy;
|
|
43
|
+
}>;
|
|
44
|
+
/** Write a policy file for an agent */
|
|
45
|
+
export declare function writeAgentPolicy(agentId: string, policy: AgentPolicy): void;
|
|
46
|
+
export { DEFAULT_POLICY, STRICT_POLICY, BUILTIN_POLICIES };
|
|
47
|
+
//# sourceMappingURL=sandbox-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-policy.d.ts","sourceRoot":"","sources":["../src/sandbox-policy.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,sDAAsD;IACtD,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,yCAAyC;IACzC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAA;IACxB,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAA;IACtB,mDAAmD;IACnD,WAAW,EAAE,OAAO,CAAA;IACpB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAA;IACnB,6CAA6C;IAC7C,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAYD,QAAA,MAAM,cAAc,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,CAUhD,CAAA;AAED,6CAA6C;AAC7C,QAAA,MAAM,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,CAU/C,CAAA;AAED,yCAAyC;AACzC,QAAA,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CA6C1D,CAAA;AAID,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAmB5D;AAuCD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAwB1G;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAuB1G;AAID,uDAAuD;AACvD,wBAAgB,YAAY,IAAI,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,CAsB1G;AAED,uCAAuC;AACvC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAyB3E;AAED,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// kbot Sandbox Policies — YAML-defined agent restrictions
|
|
2
|
+
//
|
|
3
|
+
// Inspired by NemoClaw's OpenShell sandbox.
|
|
4
|
+
// Each agent gets a policy defining what it can and cannot do.
|
|
5
|
+
//
|
|
6
|
+
// Default-deny: agents have NO permissions until explicitly granted.
|
|
7
|
+
// Policy files live in ~/.kbot/policies/agents/
|
|
8
|
+
//
|
|
9
|
+
// Example policy (coder.yaml):
|
|
10
|
+
// allowedTools:
|
|
11
|
+
// - read_file
|
|
12
|
+
// - write_file
|
|
13
|
+
// - edit_file
|
|
14
|
+
// - bash
|
|
15
|
+
// - grep
|
|
16
|
+
// - glob
|
|
17
|
+
// blockedTools:
|
|
18
|
+
// - social_post
|
|
19
|
+
// - forge_publish
|
|
20
|
+
// allowedPaths:
|
|
21
|
+
// - ./src/**
|
|
22
|
+
// - ./tests/**
|
|
23
|
+
// blockedPaths:
|
|
24
|
+
// - .env
|
|
25
|
+
// - ~/.ssh/**
|
|
26
|
+
// maxExecutionTime: 300
|
|
27
|
+
// networkAccess: false
|
|
28
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
|
|
29
|
+
import { join } from 'node:path';
|
|
30
|
+
import { homedir } from 'node:os';
|
|
31
|
+
// ── Paths ──
|
|
32
|
+
const POLICY_DIR = join(homedir(), '.kbot', 'policies', 'agents');
|
|
33
|
+
function ensureDir() {
|
|
34
|
+
if (!existsSync(POLICY_DIR))
|
|
35
|
+
mkdirSync(POLICY_DIR, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
// ── Default Policies ──
|
|
38
|
+
const DEFAULT_POLICY = {
|
|
39
|
+
allowedTools: [], // empty = all allowed
|
|
40
|
+
blockedTools: ['social_post', 'forge_publish'], // conservative defaults
|
|
41
|
+
allowedPaths: ['./**'],
|
|
42
|
+
blockedPaths: ['.env', '.env.*', '*.pem', '*.key', '~/.ssh/**', '~/.aws/**'],
|
|
43
|
+
maxExecutionTime: 300,
|
|
44
|
+
networkAccess: true,
|
|
45
|
+
shellAccess: true,
|
|
46
|
+
maxFileSize: 10 * 1024 * 1024, // 10MB
|
|
47
|
+
canInstallPackages: false,
|
|
48
|
+
};
|
|
49
|
+
/** Strict policy for untrusted/new agents */
|
|
50
|
+
const STRICT_POLICY = {
|
|
51
|
+
allowedTools: ['read_file', 'grep', 'glob', 'web_search'],
|
|
52
|
+
blockedTools: ['bash', 'write_file', 'edit_file', 'forge_tool', 'social_post'],
|
|
53
|
+
allowedPaths: ['./**'],
|
|
54
|
+
blockedPaths: ['.env', '.env.*', '*.pem', '*.key', '~/.ssh/**', '~/.aws/**', 'node_modules/**'],
|
|
55
|
+
maxExecutionTime: 60,
|
|
56
|
+
networkAccess: false,
|
|
57
|
+
shellAccess: false,
|
|
58
|
+
maxFileSize: 0,
|
|
59
|
+
canInstallPackages: false,
|
|
60
|
+
};
|
|
61
|
+
/** Built-in policies for known agents */
|
|
62
|
+
const BUILTIN_POLICIES = {
|
|
63
|
+
coder: {
|
|
64
|
+
allowedTools: [],
|
|
65
|
+
blockedTools: ['social_post'],
|
|
66
|
+
shellAccess: true,
|
|
67
|
+
networkAccess: true,
|
|
68
|
+
canInstallPackages: true,
|
|
69
|
+
maxExecutionTime: 600,
|
|
70
|
+
},
|
|
71
|
+
researcher: {
|
|
72
|
+
allowedTools: ['read_file', 'grep', 'glob', 'web_search', 'url_fetch', 'research_arxiv', 'research_papers'],
|
|
73
|
+
blockedTools: ['bash', 'write_file', 'edit_file'],
|
|
74
|
+
shellAccess: false,
|
|
75
|
+
networkAccess: true,
|
|
76
|
+
canInstallPackages: false,
|
|
77
|
+
},
|
|
78
|
+
guardian: {
|
|
79
|
+
allowedTools: [],
|
|
80
|
+
blockedTools: ['social_post', 'forge_publish'],
|
|
81
|
+
shellAccess: true,
|
|
82
|
+
networkAccess: true,
|
|
83
|
+
maxExecutionTime: 600,
|
|
84
|
+
},
|
|
85
|
+
hacker: {
|
|
86
|
+
allowedTools: [],
|
|
87
|
+
blockedTools: ['social_post', 'forge_publish'],
|
|
88
|
+
shellAccess: true,
|
|
89
|
+
networkAccess: true,
|
|
90
|
+
maxExecutionTime: 300,
|
|
91
|
+
},
|
|
92
|
+
writer: {
|
|
93
|
+
allowedTools: ['read_file', 'write_file', 'edit_file', 'grep', 'glob', 'web_search'],
|
|
94
|
+
blockedTools: ['bash', 'forge_tool'],
|
|
95
|
+
shellAccess: false,
|
|
96
|
+
networkAccess: true,
|
|
97
|
+
canInstallPackages: false,
|
|
98
|
+
},
|
|
99
|
+
gamedev: {
|
|
100
|
+
allowedTools: [],
|
|
101
|
+
blockedTools: ['social_post'],
|
|
102
|
+
shellAccess: true,
|
|
103
|
+
networkAccess: true,
|
|
104
|
+
canInstallPackages: true,
|
|
105
|
+
maxExecutionTime: 600,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
// ── Policy Loading ──
|
|
109
|
+
/** Load a specific agent's policy from file, falling back to builtins then defaults */
|
|
110
|
+
export function loadAgentPolicy(agentId) {
|
|
111
|
+
const filePath = join(POLICY_DIR, `${agentId}.yaml`);
|
|
112
|
+
// Try user-defined policy file first
|
|
113
|
+
if (existsSync(filePath)) {
|
|
114
|
+
try {
|
|
115
|
+
const content = readFileSync(filePath, 'utf8');
|
|
116
|
+
return parsePolicy(agentId, content);
|
|
117
|
+
}
|
|
118
|
+
catch { /* fall through to builtins */ }
|
|
119
|
+
}
|
|
120
|
+
// Try builtin policy
|
|
121
|
+
const builtin = BUILTIN_POLICIES[agentId];
|
|
122
|
+
if (builtin) {
|
|
123
|
+
return { agentId, ...DEFAULT_POLICY, ...builtin };
|
|
124
|
+
}
|
|
125
|
+
// Default policy
|
|
126
|
+
return { agentId, ...DEFAULT_POLICY };
|
|
127
|
+
}
|
|
128
|
+
/** Parse a YAML-like policy file */
|
|
129
|
+
function parsePolicy(agentId, content) {
|
|
130
|
+
const policy = { agentId, ...DEFAULT_POLICY };
|
|
131
|
+
// Parse list fields
|
|
132
|
+
const listFields = ['allowedTools', 'blockedTools', 'allowedPaths', 'blockedPaths'];
|
|
133
|
+
for (const field of listFields) {
|
|
134
|
+
const section = content.match(new RegExp(`${field}:\\n((?:\\s+-\\s+.+\\n?)+)`));
|
|
135
|
+
if (section) {
|
|
136
|
+
policy[field] = section[1]
|
|
137
|
+
.split('\n')
|
|
138
|
+
.map(l => l.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, ''))
|
|
139
|
+
.filter(Boolean);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Parse scalar fields
|
|
143
|
+
const maxTime = content.match(/maxExecutionTime:\s*(\d+)/);
|
|
144
|
+
if (maxTime)
|
|
145
|
+
policy.maxExecutionTime = Number(maxTime[1]);
|
|
146
|
+
const network = content.match(/networkAccess:\s*(true|false)/);
|
|
147
|
+
if (network)
|
|
148
|
+
policy.networkAccess = network[1] === 'true';
|
|
149
|
+
const shell = content.match(/shellAccess:\s*(true|false)/);
|
|
150
|
+
if (shell)
|
|
151
|
+
policy.shellAccess = shell[1] === 'true';
|
|
152
|
+
const maxFile = content.match(/maxFileSize:\s*(\d+)/);
|
|
153
|
+
if (maxFile)
|
|
154
|
+
policy.maxFileSize = Number(maxFile[1]);
|
|
155
|
+
const install = content.match(/canInstallPackages:\s*(true|false)/);
|
|
156
|
+
if (install)
|
|
157
|
+
policy.canInstallPackages = install[1] === 'true';
|
|
158
|
+
return policy;
|
|
159
|
+
}
|
|
160
|
+
/** Check if an agent is allowed to use a specific tool */
|
|
161
|
+
export function checkToolAccess(agentId, toolName, policy) {
|
|
162
|
+
const p = policy || loadAgentPolicy(agentId);
|
|
163
|
+
// Blocked tools take priority
|
|
164
|
+
if (p.blockedTools.includes(toolName)) {
|
|
165
|
+
return { allowed: false, reason: `Tool "${toolName}" is blocked for agent "${agentId}"` };
|
|
166
|
+
}
|
|
167
|
+
// If allowedTools is non-empty, tool must be in the list
|
|
168
|
+
if (p.allowedTools.length > 0 && !p.allowedTools.includes(toolName)) {
|
|
169
|
+
return { allowed: false, reason: `Tool "${toolName}" is not in allowed list for agent "${agentId}"` };
|
|
170
|
+
}
|
|
171
|
+
// Shell access check
|
|
172
|
+
if (toolName === 'bash' && !p.shellAccess) {
|
|
173
|
+
return { allowed: false, reason: `Shell access denied for agent "${agentId}"` };
|
|
174
|
+
}
|
|
175
|
+
// Network access check
|
|
176
|
+
if (['web_search', 'url_fetch', 'research_arxiv'].includes(toolName) && !p.networkAccess) {
|
|
177
|
+
return { allowed: false, reason: `Network access denied for agent "${agentId}"` };
|
|
178
|
+
}
|
|
179
|
+
return { allowed: true };
|
|
180
|
+
}
|
|
181
|
+
/** Check if an agent can access a file path */
|
|
182
|
+
export function checkPathAccess(agentId, filePath, policy) {
|
|
183
|
+
const p = policy || loadAgentPolicy(agentId);
|
|
184
|
+
const normalized = filePath.toLowerCase();
|
|
185
|
+
// Check blocked paths first
|
|
186
|
+
for (const blocked of p.blockedPaths) {
|
|
187
|
+
const b = blocked.toLowerCase();
|
|
188
|
+
if (b.startsWith('**/')) {
|
|
189
|
+
if (normalized.includes(b.slice(3))) {
|
|
190
|
+
return { allowed: false, reason: `Path "${filePath}" is blocked for agent "${agentId}"` };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else if (b.startsWith('*.')) {
|
|
194
|
+
if (normalized.endsWith(b.slice(1))) {
|
|
195
|
+
return { allowed: false, reason: `File type "${b}" is blocked for agent "${agentId}"` };
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
if (normalized.endsWith(b) || normalized.includes(`/${b}`)) {
|
|
200
|
+
return { allowed: false, reason: `Path "${filePath}" is blocked for agent "${agentId}"` };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return { allowed: true };
|
|
205
|
+
}
|
|
206
|
+
// ── Policy Management ──
|
|
207
|
+
/** List all agent policies (builtin + user-defined) */
|
|
208
|
+
export function listPolicies() {
|
|
209
|
+
const result = [];
|
|
210
|
+
// User-defined policies
|
|
211
|
+
ensureDir();
|
|
212
|
+
try {
|
|
213
|
+
const files = readdirSync(POLICY_DIR).filter(f => f.endsWith('.yaml'));
|
|
214
|
+
for (const f of files) {
|
|
215
|
+
const agentId = f.replace('.yaml', '');
|
|
216
|
+
result.push({ agentId, source: 'user', policy: loadAgentPolicy(agentId) });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch { /* ignore */ }
|
|
220
|
+
// Builtin policies (not already loaded from user files)
|
|
221
|
+
const userIds = new Set(result.map(r => r.agentId));
|
|
222
|
+
for (const [agentId] of Object.entries(BUILTIN_POLICIES)) {
|
|
223
|
+
if (!userIds.has(agentId)) {
|
|
224
|
+
result.push({ agentId, source: 'builtin', policy: loadAgentPolicy(agentId) });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
/** Write a policy file for an agent */
|
|
230
|
+
export function writeAgentPolicy(agentId, policy) {
|
|
231
|
+
ensureDir();
|
|
232
|
+
const filePath = join(POLICY_DIR, `${agentId}.yaml`);
|
|
233
|
+
const yaml = `# kbot Sandbox Policy for agent: ${agentId}
|
|
234
|
+
# Edit this file to customize what this agent can do.
|
|
235
|
+
|
|
236
|
+
allowedTools:
|
|
237
|
+
${policy.allowedTools.map(t => ` - ${t}`).join('\n') || ' # empty = all allowed'}
|
|
238
|
+
|
|
239
|
+
blockedTools:
|
|
240
|
+
${policy.blockedTools.map(t => ` - ${t}`).join('\n')}
|
|
241
|
+
|
|
242
|
+
allowedPaths:
|
|
243
|
+
${policy.allowedPaths.map(p => ` - "${p}"`).join('\n')}
|
|
244
|
+
|
|
245
|
+
blockedPaths:
|
|
246
|
+
${policy.blockedPaths.map(p => ` - "${p}"`).join('\n')}
|
|
247
|
+
|
|
248
|
+
maxExecutionTime: ${policy.maxExecutionTime}
|
|
249
|
+
networkAccess: ${policy.networkAccess}
|
|
250
|
+
shellAccess: ${policy.shellAccess}
|
|
251
|
+
maxFileSize: ${policy.maxFileSize}
|
|
252
|
+
canInstallPackages: ${policy.canInstallPackages}
|
|
253
|
+
`;
|
|
254
|
+
writeFileSync(filePath, yaml);
|
|
255
|
+
}
|
|
256
|
+
export { DEFAULT_POLICY, STRICT_POLICY, BUILTIN_POLICIES };
|
|
257
|
+
//# sourceMappingURL=sandbox-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-policy.js","sourceRoot":"","sources":["../src/sandbox-policy.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernel.chat/kbot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.0",
|
|
4
4
|
"description": "The only AI agent that builds its own tools. Multi-channel cognitive engine: email agent, iMessage agent, consultation pipeline, 25 specialist agents, 290+ tools, 20 providers. Runtime tool forging, Forge Registry, autopoietic health, immune self-audit. Cost-aware model routing, fallback chains, Bayesian skill routing. Embedded llama.cpp, MCP server, SDK. MIT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|