@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,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path normalization utilities for the trusted process security boundary.
|
|
3
|
+
*
|
|
4
|
+
* Provides annotation-driven normalization via `prepareToolArgs()` and a
|
|
5
|
+
* legacy heuristic fallback via `normalizeToolArgPaths()`. The heuristic
|
|
6
|
+
* is retained for defense-in-depth and as a fallback when annotations are
|
|
7
|
+
* unavailable.
|
|
8
|
+
*/
|
|
9
|
+
import { resolve } from 'node:path';
|
|
10
|
+
import { getRoleDefinition, resolveRealPath, expandTilde } from '../types/argument-roles.js';
|
|
11
|
+
export { expandTilde } from '../types/argument-roles.js';
|
|
12
|
+
/** Returns true if the string looks like a filesystem path. */
|
|
13
|
+
function looksLikePath(value) {
|
|
14
|
+
return value.startsWith('/') || value.startsWith('.') || value.startsWith('~');
|
|
15
|
+
}
|
|
16
|
+
/** Resolves a path-like string to its canonical real path, following symlinks. */
|
|
17
|
+
function normalizePath(value) {
|
|
18
|
+
return resolveRealPath(expandTilde(value));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns a new arguments object with all path-like string values
|
|
22
|
+
* fully resolved (tilde expanded, relative resolved, traversals collapsed).
|
|
23
|
+
*
|
|
24
|
+
* A string value is considered path-like if it starts with `/`, `.`, or `~`.
|
|
25
|
+
* Array values have each string element checked individually.
|
|
26
|
+
* Non-string and non-path values pass through unchanged.
|
|
27
|
+
*
|
|
28
|
+
* The input object is never mutated.
|
|
29
|
+
*
|
|
30
|
+
* @deprecated Use `prepareToolArgs()` with annotation-driven normalization.
|
|
31
|
+
* Retained as a fallback when annotations are unavailable.
|
|
32
|
+
*/
|
|
33
|
+
export function normalizeToolArgPaths(args) {
|
|
34
|
+
const result = {};
|
|
35
|
+
for (const [key, value] of Object.entries(args)) {
|
|
36
|
+
if (typeof value === 'string' && looksLikePath(value)) {
|
|
37
|
+
result[key] = normalizePath(value);
|
|
38
|
+
}
|
|
39
|
+
else if (Array.isArray(value)) {
|
|
40
|
+
result[key] = value.map(item => typeof item === 'string' && looksLikePath(item)
|
|
41
|
+
? normalizePath(item)
|
|
42
|
+
: item);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
result[key] = value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Absolute vs relative path detection
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
/** Returns true if the path is absolute (starts with `/` or `~`). */
|
|
54
|
+
function isAbsolutePath(value) {
|
|
55
|
+
return value.startsWith('/') || value.startsWith('~');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolves a relative path against the sandbox directory for policy evaluation.
|
|
59
|
+
* Applies tilde expansion first, then resolves against the sandbox base,
|
|
60
|
+
* then follows symlinks via resolveRealPath.
|
|
61
|
+
*/
|
|
62
|
+
function resolveAgainstSandbox(value, sandboxDir) {
|
|
63
|
+
const expanded = expandTilde(value);
|
|
64
|
+
const absolute = resolve(sandboxDir, expanded);
|
|
65
|
+
return resolveRealPath(absolute);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Finds the first resource-identifier role in a role array, or undefined
|
|
69
|
+
* if all roles are non-resource (e.g., 'none').
|
|
70
|
+
*/
|
|
71
|
+
function findResourceRole(roles) {
|
|
72
|
+
return roles.find(r => getRoleDefinition(r).isResourceIdentifier);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Normalizes a single argument value using a role's normalizer.
|
|
76
|
+
* Handles both string and string-array values. Non-string values
|
|
77
|
+
* pass through unchanged.
|
|
78
|
+
*/
|
|
79
|
+
function normalizeArgValue(value, normalize) {
|
|
80
|
+
if (typeof value === 'string') {
|
|
81
|
+
return normalize(value);
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
return value.map(item => typeof item === 'string' ? normalize(item) : item);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Normalizes a single path argument for transport, handling the
|
|
90
|
+
* absolute/relative split. Absolute paths get full normalization;
|
|
91
|
+
* relative paths pass through unchanged (the MCP server resolves
|
|
92
|
+
* them against its own CWD, which is the sandbox directory).
|
|
93
|
+
*/
|
|
94
|
+
function normalizePathForTransport(value, def) {
|
|
95
|
+
return normalizeArgValue(value, v => isAbsolutePath(v) ? def.normalize(v) : v);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Normalizes a single path argument for policy evaluation. Absolute
|
|
99
|
+
* paths get full normalization; relative paths are resolved against
|
|
100
|
+
* the sandbox (allowedDirectory) so the policy engine can perform
|
|
101
|
+
* containment checks with absolute canonical paths.
|
|
102
|
+
*/
|
|
103
|
+
function normalizePathForPolicy(value, def, allowedDirectory) {
|
|
104
|
+
return normalizeArgValue(value, v => isAbsolutePath(v) ? def.normalize(v) : resolveAgainstSandbox(v, allowedDirectory));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Annotation-driven normalization of tool call arguments.
|
|
108
|
+
*
|
|
109
|
+
* For each argument, looks up its annotated roles and applies the
|
|
110
|
+
* corresponding normalizer from the registry. Returns two argument
|
|
111
|
+
* objects: one for transport (MCP server) and one for policy evaluation.
|
|
112
|
+
*
|
|
113
|
+
* For path-category roles, relative paths (not starting with `/` or `~`)
|
|
114
|
+
* are treated differently:
|
|
115
|
+
* - Transport: passed through unchanged (the MCP server resolves them
|
|
116
|
+
* against its own sandbox CWD)
|
|
117
|
+
* - Policy: resolved against `allowedDirectory` so the policy engine
|
|
118
|
+
* has absolute canonical paths for containment checks
|
|
119
|
+
*
|
|
120
|
+
* When `annotation` is undefined (unknown tool), falls back to the
|
|
121
|
+
* heuristic `normalizeToolArgPaths()` for both outputs.
|
|
122
|
+
*
|
|
123
|
+
* The input object is never mutated.
|
|
124
|
+
*/
|
|
125
|
+
export function prepareToolArgs(args, annotation, allowedDirectory) {
|
|
126
|
+
if (!annotation) {
|
|
127
|
+
const fallback = normalizeToolArgPaths(args);
|
|
128
|
+
return { argsForTransport: fallback, argsForPolicy: fallback };
|
|
129
|
+
}
|
|
130
|
+
const argsForTransport = {};
|
|
131
|
+
const argsForPolicy = {};
|
|
132
|
+
for (const [key, value] of Object.entries(args)) {
|
|
133
|
+
const roles = annotation.args[key];
|
|
134
|
+
const resourceRole = roles ? findResourceRole(roles) : undefined;
|
|
135
|
+
if (resourceRole) {
|
|
136
|
+
const def = getRoleDefinition(resourceRole);
|
|
137
|
+
if (def.category === 'path' && allowedDirectory) {
|
|
138
|
+
// Path roles with sandbox context: split relative vs absolute
|
|
139
|
+
argsForTransport[key] = normalizePathForTransport(value, def);
|
|
140
|
+
argsForPolicy[key] = normalizePathForPolicy(value, def, allowedDirectory);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
// Non-path roles (URLs, opaque) or no sandbox: normalize for both
|
|
144
|
+
const transportValue = normalizeArgValue(value, def.normalize);
|
|
145
|
+
argsForTransport[key] = transportValue;
|
|
146
|
+
// Domain extraction (prepareForPolicy) is handled later by
|
|
147
|
+
// the policy engine's resolveUrlForDomainCheck().
|
|
148
|
+
argsForPolicy[key] = transportValue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
argsForTransport[key] = value;
|
|
153
|
+
argsForPolicy[key] = value;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { argsForTransport, argsForPolicy };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=path-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/trusted-process/path-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PolicyEngine -- Two-phase declarative policy evaluation.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1: Hardcoded structural invariants (protected paths, unknown tools).
|
|
5
|
+
* These are never overridden by compiled rules. Sandbox containment
|
|
6
|
+
* is checked per-role: roles whose paths are all within the sandbox
|
|
7
|
+
* are resolved here and skipped in Phase 2.
|
|
8
|
+
*
|
|
9
|
+
* Phase 2: Compiled declarative rules loaded from compiled-policy.json.
|
|
10
|
+
* Each distinct role from the tool's annotation is evaluated
|
|
11
|
+
* independently through the rule chain (first-match-wins per role).
|
|
12
|
+
* The most restrictive result wins: deny > escalate > allow.
|
|
13
|
+
* Roles already resolved by Phase 1 sandbox containment are skipped.
|
|
14
|
+
*/
|
|
15
|
+
import type { ToolCallRequest } from '../types/mcp.js';
|
|
16
|
+
import type { EvaluationResult } from './policy-types.js';
|
|
17
|
+
import type { CompiledPolicyFile, ToolAnnotationsFile, ToolAnnotation } from '../pipeline/types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Checks whether a domain matches any pattern in an allowlist.
|
|
20
|
+
* Supports exact match, `*` wildcard (matches everything),
|
|
21
|
+
* and `*.example.com` prefix wildcards (matches example.com and *.example.com).
|
|
22
|
+
*/
|
|
23
|
+
export declare function domainMatchesAllowlist(domain: string, allowedDomains: readonly string[]): boolean;
|
|
24
|
+
export declare class PolicyEngine {
|
|
25
|
+
private annotationMap;
|
|
26
|
+
private compiledPolicy;
|
|
27
|
+
private protectedPaths;
|
|
28
|
+
private allowedDirectory?;
|
|
29
|
+
private serverDomainAllowlists;
|
|
30
|
+
constructor(compiledPolicy: CompiledPolicyFile, toolAnnotations: ToolAnnotationsFile, protectedPaths: string[], allowedDirectory?: string, serverDomainAllowlists?: ReadonlyMap<string, readonly string[]>);
|
|
31
|
+
private buildAnnotationMap;
|
|
32
|
+
/** Returns the annotation for a tool, or undefined if unknown. */
|
|
33
|
+
getAnnotation(serverName: string, toolName: string): ToolAnnotation | undefined;
|
|
34
|
+
evaluate(request: ToolCallRequest): EvaluationResult;
|
|
35
|
+
/**
|
|
36
|
+
* Phase 1: Hardcoded structural invariants.
|
|
37
|
+
*
|
|
38
|
+
* 1a. Protected path check (deny)
|
|
39
|
+
* 1b. Sandbox containment for path-category roles (allow/partial)
|
|
40
|
+
* 1c. Domain allowlist for url-category roles (escalate)
|
|
41
|
+
* 1d. Unknown tool denial (deny)
|
|
42
|
+
*
|
|
43
|
+
* Uses the union of heuristic and annotation-based path extraction
|
|
44
|
+
* for defense-in-depth. Returns a StructuralResult with either a
|
|
45
|
+
* final decision or a set of roles resolved by sandbox containment.
|
|
46
|
+
*/
|
|
47
|
+
private evaluateStructuralInvariants;
|
|
48
|
+
/**
|
|
49
|
+
* Phase 2: Evaluate compiled declarative rules.
|
|
50
|
+
*
|
|
51
|
+
* For tools with multiple roles (e.g., edit_file has read-path + write-path),
|
|
52
|
+
* each role is evaluated independently through the rule chain. The most
|
|
53
|
+
* restrictive result across all roles wins (deny > escalate > allow).
|
|
54
|
+
* Roles already resolved by Phase 1 sandbox containment are skipped.
|
|
55
|
+
*
|
|
56
|
+
* For tools with no roles (e.g., list_allowed_directories), the chain is
|
|
57
|
+
* evaluated once without role filtering.
|
|
58
|
+
*/
|
|
59
|
+
private evaluateCompiledRules;
|
|
60
|
+
/**
|
|
61
|
+
* Evaluates the rule chain for a single role (or all roles if undefined).
|
|
62
|
+
*
|
|
63
|
+
* When evaluatingRole is set, only rules that are either role-agnostic
|
|
64
|
+
* (no roles/paths conditions) or relevant to the specified role are
|
|
65
|
+
* considered. First matching rule wins; default deny if none match.
|
|
66
|
+
*
|
|
67
|
+
* For roles with multiple extracted paths, delegates to
|
|
68
|
+
* evaluateRulesForMultiPaths for per-element evaluation.
|
|
69
|
+
*/
|
|
70
|
+
private evaluateRulesForRole;
|
|
71
|
+
/**
|
|
72
|
+
* Per-element path evaluation for roles with multiple paths.
|
|
73
|
+
*
|
|
74
|
+
* Each path is independently "discharged" by the first rule whose
|
|
75
|
+
* paths.within contains it. Rules without path conditions match all
|
|
76
|
+
* remaining paths. The most restrictive decision across all discharged
|
|
77
|
+
* paths wins (deny > escalate > allow). Undischarged paths default-deny.
|
|
78
|
+
*/
|
|
79
|
+
private evaluateRulesForMultiPaths;
|
|
80
|
+
/**
|
|
81
|
+
* Checks non-path conditions in a rule's `if` block: roles, server, tool, sideEffects.
|
|
82
|
+
*/
|
|
83
|
+
private ruleMatchesNonPathConditions;
|
|
84
|
+
/**
|
|
85
|
+
* Checks whether all conditions in a rule's `if` block are satisfied.
|
|
86
|
+
*/
|
|
87
|
+
private ruleMatches;
|
|
88
|
+
}
|