@provos/ironcurtain 0.1.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/LICENSE +202 -0
- package/README.md +311 -0
- package/dist/agent/index.d.ts +10 -0
- package/dist/agent/index.js +71 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/prompts.d.ts +5 -0
- package/dist/agent/prompts.js +26 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/tools.d.ts +13 -0
- package/dist/agent/tools.js +51 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +78 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/constitution.md +16 -0
- package/dist/config/generated/compiled-policy.json +236 -0
- package/dist/config/generated/test-scenarios.json +765 -0
- package/dist/config/generated/tool-annotations.json +955 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.js +151 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/mcp-servers.json +22 -0
- package/dist/config/model-provider.d.ts +49 -0
- package/dist/config/model-provider.js +78 -0
- package/dist/config/model-provider.js.map +1 -0
- package/dist/config/paths.d.ts +59 -0
- package/dist/config/paths.js +96 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/types.d.ts +89 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/user-config.d.ts +93 -0
- package/dist/config/user-config.js +309 -0
- package/dist/config/user-config.js.map +1 -0
- package/dist/hash.d.ts +17 -0
- package/dist/hash.js +34 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +11 -0
- package/dist/logger.js +93 -0
- package/dist/logger.js.map +1 -0
- package/dist/pipeline/annotate.d.ts +9 -0
- package/dist/pipeline/annotate.js +136 -0
- package/dist/pipeline/annotate.js.map +1 -0
- package/dist/pipeline/compile.d.ts +23 -0
- package/dist/pipeline/compile.js +386 -0
- package/dist/pipeline/compile.js.map +1 -0
- package/dist/pipeline/constitution-compiler.d.ts +22 -0
- package/dist/pipeline/constitution-compiler.js +197 -0
- package/dist/pipeline/constitution-compiler.js.map +1 -0
- package/dist/pipeline/generate-with-repair.d.ts +22 -0
- package/dist/pipeline/generate-with-repair.js +64 -0
- package/dist/pipeline/generate-with-repair.js.map +1 -0
- package/dist/pipeline/handwritten-scenarios.d.ts +9 -0
- package/dist/pipeline/handwritten-scenarios.js +321 -0
- package/dist/pipeline/handwritten-scenarios.js.map +1 -0
- package/dist/pipeline/llm-logger.d.ts +42 -0
- package/dist/pipeline/llm-logger.js +78 -0
- package/dist/pipeline/llm-logger.js.map +1 -0
- package/dist/pipeline/pipeline-shared.d.ts +47 -0
- package/dist/pipeline/pipeline-shared.js +145 -0
- package/dist/pipeline/pipeline-shared.js.map +1 -0
- package/dist/pipeline/policy-verifier.d.ts +46 -0
- package/dist/pipeline/policy-verifier.js +277 -0
- package/dist/pipeline/policy-verifier.js.map +1 -0
- package/dist/pipeline/scenario-generator.d.ts +11 -0
- package/dist/pipeline/scenario-generator.js +128 -0
- package/dist/pipeline/scenario-generator.js.map +1 -0
- package/dist/pipeline/tool-annotator.d.ts +24 -0
- package/dist/pipeline/tool-annotator.js +201 -0
- package/dist/pipeline/tool-annotator.js.map +1 -0
- package/dist/pipeline/types.d.ts +122 -0
- package/dist/pipeline/types.js +10 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/sandbox/index.d.ts +39 -0
- package/dist/sandbox/index.js +178 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/session/agent-session.d.ts +83 -0
- package/dist/session/agent-session.js +382 -0
- package/dist/session/agent-session.js.map +1 -0
- package/dist/session/cli-transport.d.ts +61 -0
- package/dist/session/cli-transport.js +320 -0
- package/dist/session/cli-transport.js.map +1 -0
- package/dist/session/errors.d.ts +19 -0
- package/dist/session/errors.js +33 -0
- package/dist/session/errors.js.map +1 -0
- package/dist/session/index.d.ts +29 -0
- package/dist/session/index.js +104 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/message-compactor.d.ts +32 -0
- package/dist/session/message-compactor.js +81 -0
- package/dist/session/message-compactor.js.map +1 -0
- package/dist/session/prompts.d.ts +5 -0
- package/dist/session/prompts.js +62 -0
- package/dist/session/prompts.js.map +1 -0
- package/dist/session/resource-budget-tracker.d.ts +124 -0
- package/dist/session/resource-budget-tracker.js +327 -0
- package/dist/session/resource-budget-tracker.js.map +1 -0
- package/dist/session/step-loop-detector.d.ts +63 -0
- package/dist/session/step-loop-detector.js +136 -0
- package/dist/session/step-loop-detector.js.map +1 -0
- package/dist/session/transport.d.ts +24 -0
- package/dist/session/transport.js +2 -0
- package/dist/session/transport.js.map +1 -0
- package/dist/session/truncate-result.d.ts +35 -0
- package/dist/session/truncate-result.js +71 -0
- package/dist/session/truncate-result.js.map +1 -0
- package/dist/session/types.d.ts +220 -0
- package/dist/session/types.js +6 -0
- package/dist/session/types.js.map +1 -0
- package/dist/trusted-process/audit-log.d.ts +7 -0
- package/dist/trusted-process/audit-log.js +21 -0
- package/dist/trusted-process/audit-log.js.map +1 -0
- package/dist/trusted-process/call-circuit-breaker.d.ts +33 -0
- package/dist/trusted-process/call-circuit-breaker.js +61 -0
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -0
- package/dist/trusted-process/escalation.d.ts +7 -0
- package/dist/trusted-process/escalation.js +38 -0
- package/dist/trusted-process/escalation.js.map +1 -0
- package/dist/trusted-process/index.d.ts +32 -0
- package/dist/trusted-process/index.js +151 -0
- package/dist/trusted-process/index.js.map +1 -0
- package/dist/trusted-process/mcp-client-manager.d.ts +25 -0
- package/dist/trusted-process/mcp-client-manager.js +90 -0
- package/dist/trusted-process/mcp-client-manager.js.map +1 -0
- package/dist/trusted-process/mcp-proxy-server.d.ts +24 -0
- package/dist/trusted-process/mcp-proxy-server.js +451 -0
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -0
- package/dist/trusted-process/path-utils.d.ts +50 -0
- package/dist/trusted-process/path-utils.js +158 -0
- package/dist/trusted-process/path-utils.js.map +1 -0
- package/dist/trusted-process/policy-engine.d.ts +88 -0
- package/dist/trusted-process/policy-engine.js +523 -0
- package/dist/trusted-process/policy-engine.js.map +1 -0
- package/dist/trusted-process/policy-roots.d.ts +50 -0
- package/dist/trusted-process/policy-roots.js +67 -0
- package/dist/trusted-process/policy-roots.js.map +1 -0
- package/dist/trusted-process/policy-types.d.ts +6 -0
- package/dist/trusted-process/policy-types.js +2 -0
- package/dist/trusted-process/policy-types.js.map +1 -0
- package/dist/trusted-process/sandbox-integration.d.ts +92 -0
- package/dist/trusted-process/sandbox-integration.js +184 -0
- package/dist/trusted-process/sandbox-integration.js.map +1 -0
- package/dist/types/argument-roles.d.ts +112 -0
- package/dist/types/argument-roles.js +344 -0
- package/dist/types/argument-roles.js.map +1 -0
- package/dist/types/audit.d.ts +18 -0
- package/dist/types/audit.js +2 -0
- package/dist/types/audit.js.map +1 -0
- package/dist/types/mcp.d.ts +20 -0
- package/dist/types/mcp.js +2 -0
- package/dist/types/mcp.js.map +1 -0
- package/package.json +83 -0
- package/src/config/constitution.md +16 -0
- package/src/config/generated/compiled-policy.json +236 -0
- package/src/config/generated/test-scenarios.json +765 -0
- package/src/config/generated/tool-annotations.json +955 -0
- package/src/config/mcp-servers.json +22 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-types.js","sourceRoot":"","sources":["../../src/trusted-process/policy-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox Integration -- Wraps MCP server processes in OS-level sandboxes.
|
|
3
|
+
*
|
|
4
|
+
* Each sandboxed server is spawned via a separate `srt` CLI process with
|
|
5
|
+
* its own settings file, giving each server independent sandbox infrastructure
|
|
6
|
+
* (filesystem restrictions, network proxy, and process isolation).
|
|
7
|
+
*
|
|
8
|
+
* The proxy process itself never calls SandboxManager.initialize() -- it
|
|
9
|
+
* only uses the stateless isSupportedPlatform() and checkDependencies()
|
|
10
|
+
* for the availability check.
|
|
11
|
+
*/
|
|
12
|
+
import type { MCPServerConfig, SandboxAvailabilityPolicy } from '../config/types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Result of resolving a server's sandbox configuration.
|
|
15
|
+
* Discriminated union: sandboxed servers carry the resolved config,
|
|
16
|
+
* unsandboxed servers carry the reason they were exempted.
|
|
17
|
+
*/
|
|
18
|
+
export type ResolvedSandboxConfig = {
|
|
19
|
+
readonly sandboxed: true;
|
|
20
|
+
readonly config: ResolvedSandboxParams;
|
|
21
|
+
} | {
|
|
22
|
+
readonly sandboxed: false;
|
|
23
|
+
readonly reason: 'opt-out' | 'platform-unavailable';
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Fully resolved sandbox parameters ready for srt settings.
|
|
27
|
+
* All relative paths have been resolved to absolute paths.
|
|
28
|
+
* The session sandbox directory has been injected into allowWrite.
|
|
29
|
+
*/
|
|
30
|
+
export interface ResolvedSandboxParams {
|
|
31
|
+
readonly allowWrite: readonly string[];
|
|
32
|
+
readonly denyRead: readonly string[];
|
|
33
|
+
readonly denyWrite: readonly string[];
|
|
34
|
+
readonly network: false | {
|
|
35
|
+
readonly allowedDomains: readonly string[];
|
|
36
|
+
readonly deniedDomains: readonly string[];
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Result of checking sandbox-runtime availability. */
|
|
40
|
+
export interface SandboxAvailabilityResult {
|
|
41
|
+
readonly platformSupported: boolean;
|
|
42
|
+
readonly errors: string[];
|
|
43
|
+
readonly warnings: string[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Checks sandbox dependencies and returns a structured result.
|
|
47
|
+
*
|
|
48
|
+
* Wraps SandboxManager.isSupportedPlatform() and checkDependencies()
|
|
49
|
+
* into a single call. Does NOT throw -- callers inspect the result and
|
|
50
|
+
* decide based on sandboxPolicy.
|
|
51
|
+
*/
|
|
52
|
+
export declare function checkSandboxAvailability(): SandboxAvailabilityResult;
|
|
53
|
+
/**
|
|
54
|
+
* Resolves the effective sandbox configuration for a single MCP server.
|
|
55
|
+
*
|
|
56
|
+
* Applies defaults when `sandbox` is omitted, injects the session
|
|
57
|
+
* sandbox directory into allowWrite, and resolves relative paths.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveSandboxConfig(serverConfig: MCPServerConfig, sessionSandboxDir: string, platformAvailable: boolean, policy: SandboxAvailabilityPolicy): ResolvedSandboxConfig;
|
|
60
|
+
/**
|
|
61
|
+
* Writes a per-server srt settings JSON file.
|
|
62
|
+
*
|
|
63
|
+
* Each sandboxed server gets its own settings file at
|
|
64
|
+
* `{settingsDir}/{serverName}.srt-settings.json`.
|
|
65
|
+
*
|
|
66
|
+
* Returns the absolute path to the written file.
|
|
67
|
+
*/
|
|
68
|
+
export declare function writeServerSettings(serverName: string, config: ResolvedSandboxParams, settingsDir: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Transforms a server's spawn parameters (command + args) into a
|
|
71
|
+
* sandbox-wrapped command suitable for StdioClientTransport.
|
|
72
|
+
*
|
|
73
|
+
* For sandboxed servers: returns `{ command: 'srt', args: ['-s', settingsPath, '-c', escapedCmd] }`.
|
|
74
|
+
* For unsandboxed servers: returns the original command/args unchanged.
|
|
75
|
+
*/
|
|
76
|
+
export declare function wrapServerCommand(serverName: string, command: string, args: readonly string[], sandboxConfig: ResolvedSandboxConfig, settingsDir: string): {
|
|
77
|
+
command: string;
|
|
78
|
+
args: string[];
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Cleans up per-server settings files created by writeServerSettings().
|
|
82
|
+
* Called during proxy shutdown. Safe to call even if no files were written.
|
|
83
|
+
*/
|
|
84
|
+
export declare function cleanupSettingsFiles(settingsDir: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Annotates an MCP error response when it looks like a sandbox block.
|
|
87
|
+
*
|
|
88
|
+
* When a sandboxed server returns an error matching common sandbox-blocked
|
|
89
|
+
* patterns (EPERM, EACCES, etc.) and the policy engine had allowed the call,
|
|
90
|
+
* this prefixes the error with [SANDBOX BLOCKED] to signal OS containment.
|
|
91
|
+
*/
|
|
92
|
+
export declare function annotateSandboxViolation(errorMessage: string, serverSandboxed: boolean): string;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox Integration -- Wraps MCP server processes in OS-level sandboxes.
|
|
3
|
+
*
|
|
4
|
+
* Each sandboxed server is spawned via a separate `srt` CLI process with
|
|
5
|
+
* its own settings file, giving each server independent sandbox infrastructure
|
|
6
|
+
* (filesystem restrictions, network proxy, and process isolation).
|
|
7
|
+
*
|
|
8
|
+
* The proxy process itself never calls SandboxManager.initialize() -- it
|
|
9
|
+
* only uses the stateless isSupportedPlatform() and checkDependencies()
|
|
10
|
+
* for the availability check.
|
|
11
|
+
*/
|
|
12
|
+
import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
|
|
13
|
+
import { writeFileSync, rmSync, existsSync } from 'node:fs';
|
|
14
|
+
import { join, resolve, dirname, isAbsolute } from 'node:path';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
import { quote } from 'shell-quote';
|
|
17
|
+
// ── Constants ──────────────────────────────────────────────────────────────
|
|
18
|
+
/** Sensitive directories blocked from reads by default. */
|
|
19
|
+
const DEFAULT_DENY_READ = ['~/.ssh', '~/.gnupg', '~/.aws'];
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the absolute path to the `srt` binary in node_modules.
|
|
22
|
+
* Walks up from the package root to handle npm's dependency hoisting,
|
|
23
|
+
* where bins may be in a parent node_modules/.bin/ directory.
|
|
24
|
+
*/
|
|
25
|
+
const __sandboxDirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const SRT_BIN = resolveNodeModulesBin('srt', resolve(__sandboxDirname, '..', '..'));
|
|
27
|
+
/** Pattern matching common OS-level permission errors from sandbox containment. */
|
|
28
|
+
const SANDBOX_BLOCK_PATTERN = /EACCES|EPERM|Operation not permitted|Permission denied|read-only file system/i;
|
|
29
|
+
// ── Public API ─────────────────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Checks sandbox dependencies and returns a structured result.
|
|
32
|
+
*
|
|
33
|
+
* Wraps SandboxManager.isSupportedPlatform() and checkDependencies()
|
|
34
|
+
* into a single call. Does NOT throw -- callers inspect the result and
|
|
35
|
+
* decide based on sandboxPolicy.
|
|
36
|
+
*/
|
|
37
|
+
export function checkSandboxAvailability() {
|
|
38
|
+
const platformSupported = SandboxManager.isSupportedPlatform();
|
|
39
|
+
if (!platformSupported) {
|
|
40
|
+
return { platformSupported, errors: [], warnings: [] };
|
|
41
|
+
}
|
|
42
|
+
const { errors, warnings } = SandboxManager.checkDependencies();
|
|
43
|
+
return { platformSupported, errors, warnings };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolves the effective sandbox configuration for a single MCP server.
|
|
47
|
+
*
|
|
48
|
+
* Applies defaults when `sandbox` is omitted, injects the session
|
|
49
|
+
* sandbox directory into allowWrite, and resolves relative paths.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveSandboxConfig(serverConfig, sessionSandboxDir, platformAvailable, policy) {
|
|
52
|
+
if (serverConfig.sandbox === false) {
|
|
53
|
+
return { sandboxed: false, reason: 'opt-out' };
|
|
54
|
+
}
|
|
55
|
+
if (!platformAvailable) {
|
|
56
|
+
if (policy === 'enforce') {
|
|
57
|
+
throw new Error('[sandbox] Server requires sandboxing but platform is unavailable ' +
|
|
58
|
+
'and sandboxPolicy is "enforce".');
|
|
59
|
+
}
|
|
60
|
+
return { sandboxed: false, reason: 'platform-unavailable' };
|
|
61
|
+
}
|
|
62
|
+
const sandboxConfig = serverConfig.sandbox ?? {};
|
|
63
|
+
const fsConfig = sandboxConfig.filesystem ?? {};
|
|
64
|
+
const networkConfig = sandboxConfig.network;
|
|
65
|
+
const allowWrite = buildAllowWrite(sessionSandboxDir, fsConfig.allowWrite ?? []);
|
|
66
|
+
const denyRead = fsConfig.denyRead ?? DEFAULT_DENY_READ;
|
|
67
|
+
const denyWrite = fsConfig.denyWrite ?? [];
|
|
68
|
+
const network = resolveNetworkConfig(networkConfig);
|
|
69
|
+
return {
|
|
70
|
+
sandboxed: true,
|
|
71
|
+
config: { allowWrite, denyRead, denyWrite, network },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Writes a per-server srt settings JSON file.
|
|
76
|
+
*
|
|
77
|
+
* Each sandboxed server gets its own settings file at
|
|
78
|
+
* `{settingsDir}/{serverName}.srt-settings.json`.
|
|
79
|
+
*
|
|
80
|
+
* Returns the absolute path to the written file.
|
|
81
|
+
*/
|
|
82
|
+
export function writeServerSettings(serverName, config, settingsDir) {
|
|
83
|
+
const settingsPath = join(settingsDir, `${serverName}.srt-settings.json`);
|
|
84
|
+
const network = config.network === false
|
|
85
|
+
? { allowedDomains: [], deniedDomains: [] }
|
|
86
|
+
: { allowedDomains: config.network.allowedDomains, deniedDomains: config.network.deniedDomains };
|
|
87
|
+
const settings = {
|
|
88
|
+
network,
|
|
89
|
+
filesystem: {
|
|
90
|
+
denyRead: config.denyRead,
|
|
91
|
+
allowWrite: config.allowWrite,
|
|
92
|
+
denyWrite: config.denyWrite,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
96
|
+
return settingsPath;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Transforms a server's spawn parameters (command + args) into a
|
|
100
|
+
* sandbox-wrapped command suitable for StdioClientTransport.
|
|
101
|
+
*
|
|
102
|
+
* For sandboxed servers: returns `{ command: 'srt', args: ['-s', settingsPath, '-c', escapedCmd] }`.
|
|
103
|
+
* For unsandboxed servers: returns the original command/args unchanged.
|
|
104
|
+
*/
|
|
105
|
+
export function wrapServerCommand(serverName, command, args, sandboxConfig, settingsDir) {
|
|
106
|
+
if (!sandboxConfig.sandboxed) {
|
|
107
|
+
return { command, args: [...args] };
|
|
108
|
+
}
|
|
109
|
+
const settingsPath = join(settingsDir, `${serverName}.srt-settings.json`);
|
|
110
|
+
// Resolve relative paths in args to absolute so the command works when
|
|
111
|
+
// the proxy sets cwd to the sandbox directory.
|
|
112
|
+
const resolvedArgs = args.map(a => (!isAbsolute(a) && !a.startsWith('-') ? resolve(a) : a));
|
|
113
|
+
const cmdString = quote([command, ...resolvedArgs]);
|
|
114
|
+
return {
|
|
115
|
+
command: SRT_BIN,
|
|
116
|
+
args: ['-s', settingsPath, '-c', cmdString],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Cleans up per-server settings files created by writeServerSettings().
|
|
121
|
+
* Called during proxy shutdown. Safe to call even if no files were written.
|
|
122
|
+
*/
|
|
123
|
+
export function cleanupSettingsFiles(settingsDir) {
|
|
124
|
+
try {
|
|
125
|
+
rmSync(settingsDir, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Best-effort cleanup; OS temp rotation handles leftovers
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Annotates an MCP error response when it looks like a sandbox block.
|
|
133
|
+
*
|
|
134
|
+
* When a sandboxed server returns an error matching common sandbox-blocked
|
|
135
|
+
* patterns (EPERM, EACCES, etc.) and the policy engine had allowed the call,
|
|
136
|
+
* this prefixes the error with [SANDBOX BLOCKED] to signal OS containment.
|
|
137
|
+
*/
|
|
138
|
+
export function annotateSandboxViolation(errorMessage, serverSandboxed) {
|
|
139
|
+
if (!serverSandboxed)
|
|
140
|
+
return errorMessage;
|
|
141
|
+
if (!SANDBOX_BLOCK_PATTERN.test(errorMessage))
|
|
142
|
+
return errorMessage;
|
|
143
|
+
return `[SANDBOX BLOCKED] ${errorMessage}`;
|
|
144
|
+
}
|
|
145
|
+
// ── Internal helpers ───────────────────────────────────────────────────────
|
|
146
|
+
/**
|
|
147
|
+
* Builds the allowWrite list with the session sandbox dir always included.
|
|
148
|
+
* Relative paths are resolved against the session sandbox directory.
|
|
149
|
+
*/
|
|
150
|
+
function buildAllowWrite(sessionSandboxDir, additionalPaths) {
|
|
151
|
+
const resolved = additionalPaths.map(p => isAbsolute(p) ? p : resolve(sessionSandboxDir, p));
|
|
152
|
+
return [sessionSandboxDir, ...resolved];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Resolves network config to the canonical form.
|
|
156
|
+
* `undefined` and `false` both mean no network access.
|
|
157
|
+
*/
|
|
158
|
+
function resolveNetworkConfig(config) {
|
|
159
|
+
if (!config)
|
|
160
|
+
return false;
|
|
161
|
+
return {
|
|
162
|
+
allowedDomains: config.allowedDomains,
|
|
163
|
+
deniedDomains: config.deniedDomains ?? [],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolves a binary name in node_modules/.bin/ by walking up from startDir.
|
|
168
|
+
* Handles npm's dependency hoisting where bins may live in a parent node_modules/.bin/.
|
|
169
|
+
*/
|
|
170
|
+
function resolveNodeModulesBin(binName, startDir) {
|
|
171
|
+
let dir = startDir;
|
|
172
|
+
for (;;) {
|
|
173
|
+
const candidate = join(dir, 'node_modules', '.bin', binName);
|
|
174
|
+
if (existsSync(candidate))
|
|
175
|
+
return candidate;
|
|
176
|
+
const parent = dirname(dir);
|
|
177
|
+
if (parent === dir)
|
|
178
|
+
break;
|
|
179
|
+
dir = parent;
|
|
180
|
+
}
|
|
181
|
+
// Fallback: assume it's directly under the package root
|
|
182
|
+
return join(startDir, 'node_modules', '.bin', binName);
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=sandbox-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-integration.js","sourceRoot":"","sources":["../../src/trusted-process/sandbox-integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArgumentRole Registry -- Central definition of argument role semantics.
|
|
3
|
+
*
|
|
4
|
+
* Each role is paired with metadata describing its security semantics
|
|
5
|
+
* and a normalizer function for canonicalizing argument values. This
|
|
6
|
+
* eliminates scattered hardcoded role strings and enables annotation-driven
|
|
7
|
+
* normalization instead of fragile heuristics.
|
|
8
|
+
*
|
|
9
|
+
* Roles are organized into categories that determine which structural
|
|
10
|
+
* invariant applies in the policy engine:
|
|
11
|
+
* - path: filesystem path containment checks
|
|
12
|
+
* - url: domain allowlist checks
|
|
13
|
+
* - opaque: no structural invariant (semantic meaning only)
|
|
14
|
+
*/
|
|
15
|
+
export type RoleCategory = 'path' | 'url' | 'opaque';
|
|
16
|
+
export type ArgumentRole = 'read-path' | 'write-path' | 'delete-path' | 'write-history' | 'delete-history' | 'fetch-url' | 'git-remote-url' | 'branch-name' | 'commit-message' | 'none';
|
|
17
|
+
export interface RoleDefinition {
|
|
18
|
+
readonly description: string;
|
|
19
|
+
readonly isResourceIdentifier: boolean;
|
|
20
|
+
readonly category: RoleCategory;
|
|
21
|
+
readonly normalize: (value: string) => string;
|
|
22
|
+
/** Extract the policy-relevant value (e.g., domain from URL). */
|
|
23
|
+
readonly prepareForPolicy?: (value: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Context-aware resolution for values that need sibling arguments.
|
|
26
|
+
* E.g., resolving named git remote "origin" to its URL using the
|
|
27
|
+
* `path` argument from the same tool call.
|
|
28
|
+
*/
|
|
29
|
+
readonly resolveForPolicy?: (value: string, allArgs: Record<string, unknown>) => string;
|
|
30
|
+
/**
|
|
31
|
+
* Guidance for the LLM annotation prompt. Built into the prompt
|
|
32
|
+
* dynamically from the registry -- no manual prompt maintenance.
|
|
33
|
+
*/
|
|
34
|
+
readonly annotationGuidance: string;
|
|
35
|
+
/**
|
|
36
|
+
* When set, this role is only relevant for the named MCP servers.
|
|
37
|
+
* Roles without serverNames are universal (included for all servers).
|
|
38
|
+
*/
|
|
39
|
+
readonly serverNames?: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
/** Expands a leading `~` or `~/` to the current user's home directory. */
|
|
42
|
+
export declare function expandTilde(filePath: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Resolves a filesystem path to its canonical real path, following symlinks.
|
|
45
|
+
*
|
|
46
|
+
* Tries three strategies in order:
|
|
47
|
+
* 1. `realpathSync(path)` — works for existing paths, follows all symlinks
|
|
48
|
+
* 2. `realpathSync(parent) + basename` — works for new files in existing dirs
|
|
49
|
+
* 3. `path.resolve(path)` — fallback for entirely new paths
|
|
50
|
+
*
|
|
51
|
+
* This is security-critical: without symlink resolution, a symlinked
|
|
52
|
+
* directory inside the sandbox could escape containment checks.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveRealPath(filePath: string): string;
|
|
55
|
+
/** Tilde expansion + symlink resolution to produce a canonical real path. */
|
|
56
|
+
export declare function normalizePath(value: string): string;
|
|
57
|
+
/** Normalizes an HTTP(S) URL to a canonical form. Returns value as-is on parse failure. */
|
|
58
|
+
export declare function normalizeUrl(value: string): string;
|
|
59
|
+
/** Extracts the hostname from an HTTP(S) URL. Returns value as-is on parse failure. */
|
|
60
|
+
export declare function extractDomain(value: string): string;
|
|
61
|
+
/** Normalizes a git URL (HTTP or SSH format). SSH URLs are returned as-is. */
|
|
62
|
+
export declare function normalizeGitUrl(value: string): string;
|
|
63
|
+
/** Extracts the domain from a git URL (HTTP or SSH format). */
|
|
64
|
+
export declare function extractGitDomain(value: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Resolves a git remote value to a URL for policy evaluation.
|
|
67
|
+
*
|
|
68
|
+
* If the value is already a URL (contains :// or matches SSH pattern),
|
|
69
|
+
* returns it as-is. Otherwise, treats it as a named remote and runs
|
|
70
|
+
* `git remote get-url <name>` in the repository directory (found via
|
|
71
|
+
* the `path` sibling argument).
|
|
72
|
+
*
|
|
73
|
+
* Uses execFileSync (not execSync) to avoid command injection --
|
|
74
|
+
* the value comes from agent-controlled tool call arguments.
|
|
75
|
+
*
|
|
76
|
+
* When resolution fails (repo doesn't exist, remote not found, git
|
|
77
|
+
* not installed), returns the original value. This causes the domain
|
|
78
|
+
* check to escalate (the value won't match any allowed domain),
|
|
79
|
+
* which is the correct behavior -- escalate when we can't verify.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resolveGitRemote(value: string, allArgs: Record<string, unknown>): string;
|
|
82
|
+
export declare const ARGUMENT_ROLE_REGISTRY: ReadonlyMap<ArgumentRole, RoleDefinition>;
|
|
83
|
+
/** Returns the RoleDefinition for a role. Throws if not registered. */
|
|
84
|
+
export declare function getRoleDefinition(role: ArgumentRole): RoleDefinition;
|
|
85
|
+
/** Returns all roles where isResourceIdentifier is true. */
|
|
86
|
+
export declare function getResourceRoles(): ArgumentRole[];
|
|
87
|
+
/** Type guard: returns true if the value is a valid ArgumentRole string. */
|
|
88
|
+
export declare function isArgumentRole(value: string): value is ArgumentRole;
|
|
89
|
+
/** All role values as a tuple for z.enum() compatibility. */
|
|
90
|
+
export declare function getArgumentRoleValues(): [ArgumentRole, ...ArgumentRole[]];
|
|
91
|
+
/**
|
|
92
|
+
* Returns roles relevant to a specific MCP server.
|
|
93
|
+
* Universal roles (no serverNames) are always included.
|
|
94
|
+
* Server-specific roles are included only when the server matches.
|
|
95
|
+
*/
|
|
96
|
+
export declare function getRolesForServer(serverName: string): [ArgumentRole, RoleDefinition][];
|
|
97
|
+
/** Returns all roles with the given category. */
|
|
98
|
+
export declare function getRolesByCategory(category: RoleCategory): ArgumentRole[];
|
|
99
|
+
/** Returns path-category roles only. Used by Phase 1a/1b structural invariants. */
|
|
100
|
+
export declare function getPathRoles(): ArgumentRole[];
|
|
101
|
+
/** Returns url-category roles only. Used by Phase 1c domain checks. */
|
|
102
|
+
export declare function getUrlRoles(): ArgumentRole[];
|
|
103
|
+
/**
|
|
104
|
+
* Path roles that Phase 1b sandbox containment is allowed to auto-resolve.
|
|
105
|
+
*
|
|
106
|
+
* Basic filesystem operations (read, write, delete) are safe within the
|
|
107
|
+
* sandbox boundary. Higher-risk path roles like `write-history` and
|
|
108
|
+
* `delete-history` are NOT sandbox-safe: even when the repo path is inside
|
|
109
|
+
* the sandbox, these operations require Phase 2 policy evaluation (and
|
|
110
|
+
* typically human approval) because they can destroy git history.
|
|
111
|
+
*/
|
|
112
|
+
export declare const SANDBOX_SAFE_PATH_ROLES: ReadonlySet<ArgumentRole>;
|