@alvin0/ai-agent-sdk-sandbox 0.1.3
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 +21 -0
- package/README.md +299 -0
- package/dist/index.d.ts +731 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1310 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
//#region src/entries.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Nested filesystem carve-outs.
|
|
4
|
+
*
|
|
5
|
+
* A single writable root is not enough: an agent that may write in a repository
|
|
6
|
+
* must still be kept out of `.git`, and an operator must be able to reopen one
|
|
7
|
+
* directory beneath a denied parent. Entries express that as an overlapping
|
|
8
|
+
* list resolved by path specificity — the deepest matching entry wins, so
|
|
9
|
+
* `/repo = write`, `/repo/a = deny`, `/repo/a/b = write` behaves as written.
|
|
10
|
+
*/
|
|
11
|
+
/** What one entry grants for the subtree it names. */
|
|
12
|
+
type FileSystemAccess = 'write' | 'read' | 'deny';
|
|
13
|
+
/** One carve-out in a filesystem policy. */
|
|
14
|
+
interface FileSystemEntry {
|
|
15
|
+
/** Absolute path whose subtree this entry governs. */
|
|
16
|
+
readonly path: string;
|
|
17
|
+
/** Access granted for that subtree, overriding any broader entry. */
|
|
18
|
+
readonly access: FileSystemAccess;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Order entries from broadest to narrowest so a consumer can apply them in
|
|
22
|
+
* sequence and let the most specific one win. Equal-depth entries keep a stable
|
|
23
|
+
* lexical order so a policy always produces the same backend profile.
|
|
24
|
+
*/
|
|
25
|
+
declare function orderEntries(entries: readonly FileSystemEntry[]): readonly FileSystemEntry[];
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the effective access for one target against an ordered entry list.
|
|
28
|
+
* @param target - absolute path being evaluated.
|
|
29
|
+
* @param entries - carve-outs, in any order.
|
|
30
|
+
* @param fallback - access to use when no entry covers the target.
|
|
31
|
+
*/
|
|
32
|
+
declare function accessFor(target: string, entries: readonly FileSystemEntry[], fallback: FileSystemAccess): FileSystemAccess;
|
|
33
|
+
/**
|
|
34
|
+
* Entries that carve a narrower rule *inside* `root`. A backend that grants
|
|
35
|
+
* `root` wholesale must re-apply these afterwards or the grant is too wide.
|
|
36
|
+
*/
|
|
37
|
+
declare function entriesWithin(root: string, entries: readonly FileSystemEntry[]): readonly FileSystemEntry[];
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/mode.d.ts
|
|
40
|
+
/** File-effect vocabulary shared by every sandbox backend and consumer. */
|
|
41
|
+
/**
|
|
42
|
+
* File-effect policy for confined processes. `read-only` permits only the sinks
|
|
43
|
+
* a shell requires (`/dev/null` and its platform equivalent); `workspace-write`
|
|
44
|
+
* additionally permits the workspace root and a backend-defined temp area;
|
|
45
|
+
* `danger-full-access` bypasses confinement entirely.
|
|
46
|
+
*
|
|
47
|
+
* Network reachability and process visibility are deliberately outside this
|
|
48
|
+
* vocabulary — they are governed by their own seam, not by a file-effect mode.
|
|
49
|
+
*/
|
|
50
|
+
type SandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
51
|
+
/** A confining mode — the only modes a provider can be asked to enforce. */
|
|
52
|
+
type ConfinedSandboxMode = Exclude<SandboxMode, 'danger-full-access'>;
|
|
53
|
+
/**
|
|
54
|
+
* Enforcement completeness for this host, reported as a fact rather than
|
|
55
|
+
* promised. `partial` means the selected backend cannot govern every file
|
|
56
|
+
* effect the mode promises; `fence-only` means no process confinement exists on
|
|
57
|
+
* this platform and just the in-process path fence applies, so a consumer that
|
|
58
|
+
* needs a kernel boundary must reject it rather than treat it as enforcement.
|
|
59
|
+
*/
|
|
60
|
+
type SandboxEnforcement = 'full' | 'partial' | 'fence-only';
|
|
61
|
+
/** Every mode, in widening order of authority. */
|
|
62
|
+
declare const SANDBOX_MODES: readonly SandboxMode[];
|
|
63
|
+
/** Whether an arbitrary value is one of the known modes. */
|
|
64
|
+
declare function isSandboxMode(value: unknown): value is SandboxMode;
|
|
65
|
+
/** Whether a mode still asks a provider to confine the execution. */
|
|
66
|
+
declare function isConfinedMode(mode: SandboxMode): mode is ConfinedSandboxMode;
|
|
67
|
+
/** Rank used when a narrower mode must not be widened by a weaker source. */
|
|
68
|
+
declare function modeAuthority(mode: SandboxMode): number;
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/network.d.ts
|
|
71
|
+
/**
|
|
72
|
+
* Network reachability — a seam of its own, deliberately not a file-effect mode.
|
|
73
|
+
*
|
|
74
|
+
* `SandboxMode` governs file effects and says so. Folding network reachability
|
|
75
|
+
* into it would make the mode claim something it does not decide, and a mode
|
|
76
|
+
* that lies about its scope is worse than one with a narrow one. So network is
|
|
77
|
+
* a second, independent axis carried on the same policy: a call can be
|
|
78
|
+
* `read-only` on the filesystem and still reach the internet, or writable in
|
|
79
|
+
* its workspace and reach nothing.
|
|
80
|
+
*
|
|
81
|
+
* The distinction matters because the two are enforced by different mechanisms
|
|
82
|
+
* — mount bindings versus a network namespace — and a host can provide one
|
|
83
|
+
* without the other.
|
|
84
|
+
*/
|
|
85
|
+
/**
|
|
86
|
+
* What a confined execution may reach.
|
|
87
|
+
*
|
|
88
|
+
* `loopback` is not a weaker `deny`: it is what a command needs when the
|
|
89
|
+
* deployment runs a proxy or a language server it is meant to talk to, and
|
|
90
|
+
* nothing else. On a host whose only mechanism is a network namespace the two
|
|
91
|
+
* enforce identically, which the enforcement report says rather than hides.
|
|
92
|
+
*/
|
|
93
|
+
type NetworkMode = 'deny' | 'loopback' | 'allow-all';
|
|
94
|
+
/** Every network mode, in widening order of reach. */
|
|
95
|
+
declare const NETWORK_MODES: readonly NetworkMode[];
|
|
96
|
+
/** How completely a backend enforces a network mode. */
|
|
97
|
+
type NetworkEnforcement = 'full' | 'loopback-only' | 'none';
|
|
98
|
+
/** Whether an arbitrary value is one of the known network modes. */
|
|
99
|
+
declare function isNetworkMode(value: unknown): value is NetworkMode;
|
|
100
|
+
/** Rank used so an untrusted request can narrow reach but never widen it. */
|
|
101
|
+
declare function networkAuthority(mode: NetworkMode): number;
|
|
102
|
+
/**
|
|
103
|
+
* Narrow a network mode toward a stricter one, refusing to widen.
|
|
104
|
+
* @param ceiling - the reach already permitted.
|
|
105
|
+
* @param requested - the reach being asked for.
|
|
106
|
+
* @returns the stricter of the two.
|
|
107
|
+
*/
|
|
108
|
+
declare function narrowNetwork(ceiling: NetworkMode, requested: NetworkMode | undefined): NetworkMode;
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/approval.d.ts
|
|
111
|
+
/** How long a minted approval remains usable. */
|
|
112
|
+
type SandboxApprovalScope = 'single-call' | 'session';
|
|
113
|
+
/** What an approval permits, beyond what the session already allows. */
|
|
114
|
+
interface SandboxApprovalGrant {
|
|
115
|
+
/**
|
|
116
|
+
* Whether the approval survives the call it was minted for.
|
|
117
|
+
*
|
|
118
|
+
* `single-call` — the default — is consumed the first time a policy is
|
|
119
|
+
* resolved with it, so a grant given for one operation cannot be replayed
|
|
120
|
+
* for the next. A person approving "read this file" approved one read.
|
|
121
|
+
*/
|
|
122
|
+
readonly scope?: SandboxApprovalScope;
|
|
123
|
+
/** Wall-clock deadline in epoch milliseconds, after which it is refused. */
|
|
124
|
+
readonly expiresAt?: number;
|
|
125
|
+
/** Mode the approval raises this call to. */
|
|
126
|
+
readonly mode?: SandboxMode;
|
|
127
|
+
/** Entries the approval may add, including widening ones. */
|
|
128
|
+
readonly entries?: readonly FileSystemEntry[];
|
|
129
|
+
/** Network reach the approval raises this call to. */
|
|
130
|
+
readonly network?: NetworkMode;
|
|
131
|
+
/** Free-text reason, carried for audit; never interpreted. */
|
|
132
|
+
readonly justification?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* An approval token. Structurally it is just its grant, but only a value minted
|
|
136
|
+
* by {@link approveSandboxEscalation} is accepted — a look-alike object, however
|
|
137
|
+
* carefully shaped, is refused.
|
|
138
|
+
*/
|
|
139
|
+
interface SandboxApproval extends SandboxApprovalGrant {
|
|
140
|
+
readonly approved: true;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Mint an approval. Call this only after the host has actually authorized the
|
|
144
|
+
* escalation; the SDK cannot tell an approved grant from a requested one, which
|
|
145
|
+
* is precisely why this call has to be the place the distinction is made.
|
|
146
|
+
*/
|
|
147
|
+
declare function approveSandboxEscalation(grant: SandboxApprovalGrant): SandboxApproval;
|
|
148
|
+
/** Whether a value is an approval this module minted. */
|
|
149
|
+
declare function isSandboxApproval(value: unknown): value is SandboxApproval;
|
|
150
|
+
/** Whether a minted approval has already been used up. */
|
|
151
|
+
declare function isSandboxApprovalSpent(approval: SandboxApproval): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Accept an approval, or refuse it loudly.
|
|
154
|
+
* @throws SandboxPolicyError when the value was not minted here — which is what
|
|
155
|
+
* a forged approval arriving through a tool payload looks like.
|
|
156
|
+
*/
|
|
157
|
+
declare function requireSandboxApproval(value: unknown, now?: number): SandboxApproval;
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/exec.d.ts
|
|
160
|
+
/**
|
|
161
|
+
* Reading a command for what it *does*, not just what it touches.
|
|
162
|
+
*
|
|
163
|
+
* The file seam cannot tell `systemctl status nginx` from `systemctl restart
|
|
164
|
+
* nginx`: both are argv, neither writes a file the policy cares about, and one
|
|
165
|
+
* observes while the other changes the machine. Deciding between them needs the
|
|
166
|
+
* command read semantically, before any of it runs.
|
|
167
|
+
*
|
|
168
|
+
* This is a classifier, and a classifier is a guess. Two rules keep the guess
|
|
169
|
+
* from becoming a hazard: a command it does not recognise is never allowed, and
|
|
170
|
+
* a command that hides other commands — a shell string, a pipeline, a chain —
|
|
171
|
+
* is classified by the riskiest thing inside it rather than by its wrapper.
|
|
172
|
+
*/
|
|
173
|
+
/** What a command does to the machine, in increasing order of consequence. */
|
|
174
|
+
type ExecCapability = 'observe' | 'use' | 'modify' | 'service-control' | 'package-install' | 'privilege' | 'credential' | 'critical' | 'unknown';
|
|
175
|
+
/** What a harness should do with a command carrying that capability. */
|
|
176
|
+
type ExecOutcome = 'allow' | 'allow-scoped' | 'ask-approval' | 'deny';
|
|
177
|
+
/** One classified command, and why it was classified that way. */
|
|
178
|
+
interface ExecClassification {
|
|
179
|
+
readonly capability: ExecCapability;
|
|
180
|
+
readonly outcome: ExecOutcome;
|
|
181
|
+
/** The program the decision was made about, after unwrapping. */
|
|
182
|
+
readonly program: string;
|
|
183
|
+
/** Why, in terms a person approving it can check. */
|
|
184
|
+
readonly reason: string;
|
|
185
|
+
/** Every command found inside a shell string or chain, already classified. */
|
|
186
|
+
readonly parts: readonly ExecClassification[];
|
|
187
|
+
}
|
|
188
|
+
/** The outcome each capability maps to, before a deployment adjusts it. */
|
|
189
|
+
declare const DEFAULT_EXEC_OUTCOMES: Readonly<Record<ExecCapability, ExecOutcome>>;
|
|
190
|
+
/**
|
|
191
|
+
* Classify one command.
|
|
192
|
+
* @param argv - the exact argv, program first. A shell string is read through.
|
|
193
|
+
* @param outcomes - the capability-to-outcome mapping a deployment uses.
|
|
194
|
+
*/
|
|
195
|
+
declare function classifyExec(argv: readonly string[], outcomes?: Readonly<Record<ExecCapability, ExecOutcome>>): ExecClassification;
|
|
196
|
+
/**
|
|
197
|
+
* Every command an argv actually runs.
|
|
198
|
+
*
|
|
199
|
+
* A shell invocation carries its real command in a string, and that string can
|
|
200
|
+
* hold several. Splitting it with a pattern cannot work: `grep -E 'a|b'` puts a
|
|
201
|
+
* separator inside a quoted word, and a pattern either splits there — inventing
|
|
202
|
+
* commands out of a regex — or refuses to split anywhere a quote appears. The
|
|
203
|
+
* script is therefore walked one character at a time, so a separator only
|
|
204
|
+
* separates when nothing is quoting it.
|
|
205
|
+
*/
|
|
206
|
+
declare function splitCommands(argv: readonly string[]): readonly (readonly string[])[];
|
|
207
|
+
/**
|
|
208
|
+
* Split a shell script into commands, respecting quotes and escapes.
|
|
209
|
+
*
|
|
210
|
+
* Deliberately not a shell parser: it does not expand, substitute, or
|
|
211
|
+
* understand control flow. It answers one question — which words belong to
|
|
212
|
+
* which command — and leaves the rest to the classifier, which treats anything
|
|
213
|
+
* it cannot read as something to ask about.
|
|
214
|
+
*/
|
|
215
|
+
declare function tokenizeScript(script: string): readonly (readonly string[])[];
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/errors.d.ts
|
|
218
|
+
/** Fail-closed error surface. Silent unconfined passthrough is never legal. */
|
|
219
|
+
/** Thrown when no backend on this host can enforce a confining policy. */
|
|
220
|
+
declare class SandboxUnavailableError extends Error {
|
|
221
|
+
readonly platform: string;
|
|
222
|
+
readonly code: 'SANDBOX_UNAVAILABLE';
|
|
223
|
+
/** Runner ids that were considered for this platform, in chain order. */
|
|
224
|
+
readonly attempted: readonly string[];
|
|
225
|
+
constructor(platform: string, attempted?: readonly string[], detail?: string);
|
|
226
|
+
}
|
|
227
|
+
/** Thrown by the in-process fence when a mutation leaves the permitted roots. */
|
|
228
|
+
declare class SandboxDeniedError extends Error {
|
|
229
|
+
readonly path: string;
|
|
230
|
+
readonly mode: string;
|
|
231
|
+
readonly writableRoots: readonly string[];
|
|
232
|
+
readonly code: 'SANDBOX_DENIED';
|
|
233
|
+
constructor(path: string, mode: string, writableRoots: readonly string[]);
|
|
234
|
+
}
|
|
235
|
+
/** Thrown when a policy is structurally unusable before any backend is asked. */
|
|
236
|
+
declare class SandboxPolicyError extends Error {
|
|
237
|
+
readonly code: 'SANDBOX_POLICY_INVALID';
|
|
238
|
+
constructor(message: string);
|
|
239
|
+
}
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/policy.d.ts
|
|
242
|
+
/** The complete file-effect policy resolved for one capability call. */
|
|
243
|
+
interface SandboxExecutionPolicy {
|
|
244
|
+
/** The file-effect mode this execution runs under. */
|
|
245
|
+
readonly mode: SandboxMode;
|
|
246
|
+
/** Absolute root directory `workspace-write` may write under. */
|
|
247
|
+
readonly workspaceRoot: string;
|
|
248
|
+
/** Nested carve-outs layered over the mode's base grant. */
|
|
249
|
+
readonly entries?: readonly FileSystemEntry[];
|
|
250
|
+
/** Untrusted per-call carve-outs, kept separate so they can only intersect. */
|
|
251
|
+
readonly restrictions?: readonly FileSystemEntry[];
|
|
252
|
+
/** Carve-outs carried by a minted approval and therefore allowed to widen. */
|
|
253
|
+
readonly approvedEntries?: readonly FileSystemEntry[];
|
|
254
|
+
/**
|
|
255
|
+
* The access in force where no layer applies.
|
|
256
|
+
*
|
|
257
|
+
* `read` — the default — means the host is readable and a policy closes
|
|
258
|
+
* paths one at a time, which is a deny-list: it protects what someone
|
|
259
|
+
* remembered to name. `deny` inverts that into an allow-list, where nothing
|
|
260
|
+
* is readable until an entry says so, and a path nobody thought about is
|
|
261
|
+
* closed rather than open.
|
|
262
|
+
*/
|
|
263
|
+
readonly baseline?: FileSystemAccess;
|
|
264
|
+
/**
|
|
265
|
+
* What this execution may reach over the network. Independent of
|
|
266
|
+
* {@link SandboxExecutionPolicy.mode}, which governs file effects only.
|
|
267
|
+
*/
|
|
268
|
+
readonly network?: NetworkMode;
|
|
269
|
+
/** Opaque calling-session identity; backends key per-session state off it. */
|
|
270
|
+
readonly sessionId?: string;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* A policy narrowed to a confining mode — the only shape a provider accepts.
|
|
274
|
+
* Resolution happens at the consumer boundary; the provider treats what it
|
|
275
|
+
* receives as fully specified and never re-defaults anything.
|
|
276
|
+
*/
|
|
277
|
+
interface SandboxPolicy extends SandboxExecutionPolicy {
|
|
278
|
+
readonly mode: ConfinedSandboxMode;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Inputs that select the policy for one capability call.
|
|
282
|
+
*
|
|
283
|
+
* `mode` and `entries` are the UNTRUSTED half: they arrive from whatever asked
|
|
284
|
+
* for the execution, which in an agent is a model-authored tool payload. They
|
|
285
|
+
* may only narrow. Widening lives behind {@link approval}, which a tool payload
|
|
286
|
+
* cannot contain because it is a capability rather than data.
|
|
287
|
+
*/
|
|
288
|
+
interface SandboxPolicyRequest {
|
|
289
|
+
/**
|
|
290
|
+
* The mode the caller asks for. Honoured only when it is at least as strict
|
|
291
|
+
* as the session's own mode — a request can tighten its own execution, never
|
|
292
|
+
* loosen it.
|
|
293
|
+
*/
|
|
294
|
+
readonly mode?: SandboxMode;
|
|
295
|
+
/** The calling session's mode, as last logged for that session. */
|
|
296
|
+
readonly sessionMode?: SandboxMode;
|
|
297
|
+
/** The calling session's immutable cwd; becomes the workspace boundary. */
|
|
298
|
+
readonly cwd?: string;
|
|
299
|
+
/**
|
|
300
|
+
* Carve-outs the caller asks for. Restrictions only: a `write` entry here is
|
|
301
|
+
* an escalation attempt and is refused, because granting write to `.git` or
|
|
302
|
+
* `~/.ssh` defeats the boundary just as completely as raising the mode.
|
|
303
|
+
*/
|
|
304
|
+
readonly entries?: readonly FileSystemEntry[];
|
|
305
|
+
/** The network reach the caller asks for; honoured only when it narrows. */
|
|
306
|
+
readonly network?: NetworkMode;
|
|
307
|
+
/** An approval minted by `approveSandboxEscalation`; the only way to widen. */
|
|
308
|
+
readonly approval?: SandboxApproval;
|
|
309
|
+
/** Opaque calling-session identity. */
|
|
310
|
+
readonly sessionId?: string;
|
|
311
|
+
}
|
|
312
|
+
/** Deployment-level fallbacks applied when a request omits them. */
|
|
313
|
+
interface SandboxPolicyDefaults {
|
|
314
|
+
/** Mode for calls that carry neither an override nor a session mode. */
|
|
315
|
+
readonly mode: SandboxMode;
|
|
316
|
+
/** Workspace root for agentless calls and sessions without a cwd. */
|
|
317
|
+
readonly workspaceRoot: string;
|
|
318
|
+
/** Carve-outs that always apply, before request-supplied ones. */
|
|
319
|
+
readonly entries?: readonly FileSystemEntry[];
|
|
320
|
+
/** Access where no layer applies; see {@link SandboxExecutionPolicy.baseline}. */
|
|
321
|
+
readonly baseline?: FileSystemAccess;
|
|
322
|
+
/**
|
|
323
|
+
* Network reach for calls that do not narrow it. Defaults to `allow-all`,
|
|
324
|
+
* which is what this package did before the seam existed; a deployment
|
|
325
|
+
* running anything untrusted should set `deny` and widen per call.
|
|
326
|
+
*/
|
|
327
|
+
readonly network?: NetworkMode;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Resolve the complete policy for one capability call.
|
|
331
|
+
*
|
|
332
|
+
* Authority only ever decreases across untrusted inputs: the deployment default
|
|
333
|
+
* and the session's mode set a ceiling, a request may narrow beneath it, and a
|
|
334
|
+
* minted approval is the single path that raises it. A session cwd is its
|
|
335
|
+
* `workspace-write` boundary; the configured root is the fallback for agentless
|
|
336
|
+
* calls and sessions without a cwd.
|
|
337
|
+
* @param request - the calling session's untrusted ask, plus any approval.
|
|
338
|
+
* @param defaults - deployment mode, workspace root, and standing carve-outs.
|
|
339
|
+
* @throws SandboxPolicyError when a request tries to widen without an approval.
|
|
340
|
+
*/
|
|
341
|
+
declare function resolveSandboxPolicy(request: SandboxPolicyRequest, defaults: SandboxPolicyDefaults): SandboxExecutionPolicy;
|
|
342
|
+
/**
|
|
343
|
+
* Narrow a resolved policy to the confining shape a provider accepts.
|
|
344
|
+
* @returns the confining policy, or `undefined` under `danger-full-access`,
|
|
345
|
+
* whose consumer spawns its original argv and never calls the provider.
|
|
346
|
+
*/
|
|
347
|
+
declare function confiningPolicy(policy: SandboxExecutionPolicy): SandboxPolicy | undefined;
|
|
348
|
+
/**
|
|
349
|
+
* Narrow a policy toward a stricter mode without widening it. Used where a
|
|
350
|
+
* consumer may tighten a caller's policy but must never loosen it.
|
|
351
|
+
*/
|
|
352
|
+
declare function narrowPolicy(policy: SandboxExecutionPolicy, mode: SandboxMode): SandboxExecutionPolicy;
|
|
353
|
+
//#endregion
|
|
354
|
+
//#region src/classify.d.ts
|
|
355
|
+
/**
|
|
356
|
+
* Outcome classification.
|
|
357
|
+
*
|
|
358
|
+
* Two failures look alike in a shell but mean opposite things. A *denial* means
|
|
359
|
+
* confinement worked and blocked the command. A *runner failure* means the
|
|
360
|
+
* sandbox itself refused or crashed and the command never ran at all. Reporting
|
|
361
|
+
* the second as the first sends a model off rewriting correct code, so runner
|
|
362
|
+
* failure is always checked first and never inferred from an exit code alone.
|
|
363
|
+
*/
|
|
364
|
+
/** Evidence that a runner failed before it executed the wrapped command. */
|
|
365
|
+
interface RunnerFailureRule {
|
|
366
|
+
/** Nonzero exits this rule may match; omitted permits any nonzero exit. */
|
|
367
|
+
readonly allowedExitCodes?: readonly number[];
|
|
368
|
+
/** Case-insensitive substrings identifying a fatal runner diagnostic. */
|
|
369
|
+
readonly fatalSignatures: readonly string[];
|
|
370
|
+
/** Benign lines removed by exact, case-insensitive full-line equality first. */
|
|
371
|
+
readonly informationalLines?: readonly string[];
|
|
372
|
+
/**
|
|
373
|
+
* Substrings that disqualify a line from proving runner failure, applied
|
|
374
|
+
* before {@link fatalSignatures}. A runner reports the child's failed `exec`
|
|
375
|
+
* under its own name and often its own exit code, so the prefix that
|
|
376
|
+
* identifies its diagnostics also matches an ordinary missing program; this
|
|
377
|
+
* is how that one case is carved back out.
|
|
378
|
+
*/
|
|
379
|
+
readonly excludedSignatures?: readonly string[];
|
|
380
|
+
}
|
|
381
|
+
/** What a finished confined command turned out to be. */
|
|
382
|
+
type SandboxOutcomeKind = 'success' | 'runner-failure' | 'denied' | 'command-failure';
|
|
383
|
+
/** The observable result of spawning a confined argv. */
|
|
384
|
+
interface CommandOutcome {
|
|
385
|
+
/** Process exit code; a signalled process reports its conventional code. */
|
|
386
|
+
readonly exitCode: number;
|
|
387
|
+
/** Stderr text as produced, never rewritten by classification. */
|
|
388
|
+
readonly stderr: string;
|
|
389
|
+
/** Terminating signal name, when the host reports one. */
|
|
390
|
+
readonly signal?: string | null;
|
|
391
|
+
/**
|
|
392
|
+
* Whether the runner reported, on a channel of its own, that it executed the
|
|
393
|
+
* command. Stderr cannot answer this: the runner and the command share that
|
|
394
|
+
* stream, so a command can print the runner's fatal signature and exit with
|
|
395
|
+
* the runner's code, and claim it never ran. When this is `true` no
|
|
396
|
+
* runner-failure rule applies, because the claim is already contradicted by
|
|
397
|
+
* evidence the command could not write.
|
|
398
|
+
*/
|
|
399
|
+
readonly childStarted?: boolean;
|
|
400
|
+
}
|
|
401
|
+
/** Evidence a consumer needs to classify one confined command's outcome. */
|
|
402
|
+
interface SandboxClassificationInput {
|
|
403
|
+
/** Denial dialect of the backend that actually wrapped this command. */
|
|
404
|
+
readonly denialSignatures: readonly string[];
|
|
405
|
+
/** Structured runner-failure evidence for that same backend. */
|
|
406
|
+
readonly runnerFailureRules: readonly RunnerFailureRule[];
|
|
407
|
+
}
|
|
408
|
+
/** A classified outcome plus the stderr line that proved it. */
|
|
409
|
+
interface SandboxClassification {
|
|
410
|
+
readonly kind: SandboxOutcomeKind;
|
|
411
|
+
/** The stderr line that matched, kept verbatim for the caller to surface. */
|
|
412
|
+
readonly evidence?: string;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Classify one confined command's outcome.
|
|
416
|
+
*
|
|
417
|
+
* Runner failure is tested first, then a seccomp kill (deterministic, no text
|
|
418
|
+
* matching needed), then the backend's own denial dialect. A cross-backend
|
|
419
|
+
* union of denial strings is deliberately not used: it would claim denials a
|
|
420
|
+
* given backend never produces.
|
|
421
|
+
*/
|
|
422
|
+
declare function classifyOutcome(outcome: CommandOutcome, input: SandboxClassificationInput): SandboxClassification;
|
|
423
|
+
/**
|
|
424
|
+
* Append a short, factual note to stderr explaining a sandbox outcome, so a
|
|
425
|
+
* reader never has to infer confinement from a bare error string.
|
|
426
|
+
*/
|
|
427
|
+
declare function annotateStderr(stderr: string, classification: SandboxClassification, mode: string): string;
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/provider.d.ts
|
|
430
|
+
/** The argv to spawn in place of the caller's own, plus how to read its result. */
|
|
431
|
+
interface ConfinedArgv {
|
|
432
|
+
/** The wrapped argv: runner, profile arguments, separator, caller's argv. */
|
|
433
|
+
readonly argv: readonly string[];
|
|
434
|
+
/** How completely the selected backend enforces this policy's file effects. */
|
|
435
|
+
readonly enforcement: SandboxEnforcement;
|
|
436
|
+
/**
|
|
437
|
+
* How completely it enforces the policy's network reach. `none` means the
|
|
438
|
+
* command can reach whatever the host can, whatever the policy asked for —
|
|
439
|
+
* a separate fact from file enforcement, because a host can provide one
|
|
440
|
+
* mechanism and not the other.
|
|
441
|
+
*/
|
|
442
|
+
readonly networkEnforcement: NetworkEnforcement;
|
|
443
|
+
/** Identifier of the backend that produced this wrap. */
|
|
444
|
+
readonly backend: string;
|
|
445
|
+
/**
|
|
446
|
+
* The selected backend's denial DIALECT: the stderr substrings a file effect
|
|
447
|
+
* denied by THIS backend produces. Matched instead of a cross-backend union,
|
|
448
|
+
* which would claim denials this backend never emits.
|
|
449
|
+
*/
|
|
450
|
+
readonly denialSignatures: readonly string[];
|
|
451
|
+
/** Structured evidence that the runner failed before the command ran. */
|
|
452
|
+
readonly runnerFailureRules: readonly RunnerFailureRule[];
|
|
453
|
+
/** Environment additions marking the confinement for child processes. */
|
|
454
|
+
readonly env: Readonly<Record<string, string>>;
|
|
455
|
+
/**
|
|
456
|
+
* File descriptor the runner reports its own status on, when it has one.
|
|
457
|
+
*
|
|
458
|
+
* The consumer must give the spawned process a pipe at this descriptor and
|
|
459
|
+
* read it back: it is the only channel a confined command cannot write to,
|
|
460
|
+
* and therefore the only evidence that distinguishes a runner that failed
|
|
461
|
+
* from a command claiming the runner failed.
|
|
462
|
+
*/
|
|
463
|
+
readonly statusFd?: number;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* In-process path fence. It governs file effects a tool performs itself, which
|
|
467
|
+
* no process sandbox can see, and is the only enforcement available on a
|
|
468
|
+
* platform without a process backend.
|
|
469
|
+
*/
|
|
470
|
+
interface FsFence {
|
|
471
|
+
/** Throw `SandboxDeniedError` unless the path may be written. */
|
|
472
|
+
assertWritable(path: string): Promise<void>;
|
|
473
|
+
/** Whether the path may be written, without throwing. */
|
|
474
|
+
isWritable(path: string): Promise<boolean>;
|
|
475
|
+
/** Whether the path may be read; `deny` carve-outs make this false. */
|
|
476
|
+
isReadable(path: string): Promise<boolean>;
|
|
477
|
+
/** The roots this fence permits writes under, for surfacing to a caller. */
|
|
478
|
+
readonly writableRoots: readonly string[];
|
|
479
|
+
/** Whether the path's inode carries another name this policy never examined. */
|
|
480
|
+
isAliased(path: string): Promise<boolean>;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Abstract process-sandbox service. `confine` must return an enforcing argv or
|
|
484
|
+
* fail closed; silent unconfined passthrough is forbidden.
|
|
485
|
+
*/
|
|
486
|
+
interface SandboxProvider {
|
|
487
|
+
/** Stable identifier of this provider implementation. */
|
|
488
|
+
readonly id: string;
|
|
489
|
+
/**
|
|
490
|
+
* Wrap `argv` so it executes confined under `policy` on this host.
|
|
491
|
+
* @param argv - the exact argv the caller is about to spawn, NOT a shell
|
|
492
|
+
* string; a shell-shaped consumer passes `['bash', '-c', command]`.
|
|
493
|
+
* @param policy - the file-effect policy this execution runs under.
|
|
494
|
+
* @returns the argv to spawn instead, plus its enforcement and dialects.
|
|
495
|
+
*/
|
|
496
|
+
confine(argv: readonly string[], policy: SandboxPolicy): Promise<ConfinedArgv>;
|
|
497
|
+
/** Build the in-process fence for the same policy the backends receive. */
|
|
498
|
+
fence(policy: SandboxPolicy): FsFence;
|
|
499
|
+
}
|
|
500
|
+
/** Filesystem facts the Universal contract cannot read for itself. */
|
|
501
|
+
interface PathResolver {
|
|
502
|
+
/** Canonical path with symlinks resolved, for the nearest existing ancestor. */
|
|
503
|
+
realpath(path: string): Promise<string>;
|
|
504
|
+
/** Whether the path currently exists. */
|
|
505
|
+
exists(path: string): Promise<boolean>;
|
|
506
|
+
/**
|
|
507
|
+
* The target of a symbolic link, or `undefined` when the path is not one.
|
|
508
|
+
*
|
|
509
|
+
* Existence has to be judged without following links: a link pointing at a
|
|
510
|
+
* path that does not exist yet still exists itself, and treating it as absent
|
|
511
|
+
* makes the resolver judge the link's own name instead of where it leads —
|
|
512
|
+
* which is inside the workspace, and therefore writable.
|
|
513
|
+
*/
|
|
514
|
+
readLink?(path: string): Promise<string | undefined>;
|
|
515
|
+
/**
|
|
516
|
+
* How many names refer to this file's inode, when the host can say.
|
|
517
|
+
*
|
|
518
|
+
* A path boundary cannot see a hard link: two names for one inode, one inside
|
|
519
|
+
* the workspace and one outside, let a write reach past the boundary through
|
|
520
|
+
* the inside name. A count above one means the file is reachable under
|
|
521
|
+
* another name this policy never examined.
|
|
522
|
+
*/
|
|
523
|
+
hardLinkCount?(path: string): Promise<number>;
|
|
524
|
+
}
|
|
525
|
+
//#endregion
|
|
526
|
+
//#region src/roots.d.ts
|
|
527
|
+
/**
|
|
528
|
+
* Directory names never writable inside a granted root. Writing `.git` lets a
|
|
529
|
+
* command install a hook that runs arbitrary code on the next git invocation,
|
|
530
|
+
* which defeats the point of confining the command; the credential files are
|
|
531
|
+
* there so a confined command cannot rewrite the caller's own authentication.
|
|
532
|
+
* They stay readable — this is a write boundary, not a read boundary.
|
|
533
|
+
*/
|
|
534
|
+
declare const PROTECTED_SUBPATHS: readonly string[];
|
|
535
|
+
/** Where a layer came from, which decides ties at equal path specificity. */
|
|
536
|
+
type GrantOrigin = 'mode' | 'protected' | 'entry' | 'restriction' | 'approval';
|
|
537
|
+
/** One subtree's access, overriding whatever the layers beneath it said. */
|
|
538
|
+
interface GrantLayer {
|
|
539
|
+
/** Absolute, normalized path whose subtree this layer governs. */
|
|
540
|
+
readonly path: string;
|
|
541
|
+
/** Access this layer establishes for that subtree. */
|
|
542
|
+
readonly access: FileSystemAccess;
|
|
543
|
+
/** What contributed the layer; an explicit entry outranks a generated one. */
|
|
544
|
+
readonly origin: GrantOrigin;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* The baseline every policy starts from: the host is readable and nothing is
|
|
548
|
+
* writable. Layers only ever move a subtree away from this.
|
|
549
|
+
*/
|
|
550
|
+
declare const BASELINE_ACCESS: FileSystemAccess;
|
|
551
|
+
/** Optional platform inputs the caller knows and this package must not guess. */
|
|
552
|
+
interface WritableRootOptions {
|
|
553
|
+
/** Temp directories `workspace-write` may also use (e.g. the OS temp root). */
|
|
554
|
+
readonly tempRoots?: readonly string[];
|
|
555
|
+
/** Whether to layer {@link PROTECTED_SUBPATHS} under every granted root. */
|
|
556
|
+
readonly protectSubpaths?: boolean;
|
|
557
|
+
/**
|
|
558
|
+
* Absolute paths the platform hides outright — credential stores and host
|
|
559
|
+
* daemon sockets. Layered as `deny` above the mode grant and below any
|
|
560
|
+
* explicit entry, so a deployment can still reopen one deliberately while a
|
|
561
|
+
* tool-supplied restriction cannot widen it.
|
|
562
|
+
*/
|
|
563
|
+
readonly deniedPaths?: readonly string[];
|
|
564
|
+
/**
|
|
565
|
+
* Permit writes to a file whose inode carries more than one name. Off by
|
|
566
|
+
* default: a hard link reaching out of the workspace is otherwise invisible
|
|
567
|
+
* to a boundary made of paths.
|
|
568
|
+
*/
|
|
569
|
+
readonly allowAliasedWrites?: boolean;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Resolve a policy into the ordered layers that express it.
|
|
573
|
+
*
|
|
574
|
+
* Layers are sorted broadest to narrowest, and an explicit entry wins a tie at
|
|
575
|
+
* equal depth so a deployment can deliberately reopen a protected subpath. A
|
|
576
|
+
* layer that would not change the access already in force is dropped, so the
|
|
577
|
+
* result carries no mount or profile rule that does nothing.
|
|
578
|
+
*/
|
|
579
|
+
declare function grantLayers(policy: SandboxPolicy, options?: WritableRootOptions): readonly GrantLayer[];
|
|
580
|
+
/**
|
|
581
|
+
* The access in force at one path, given layers already applied in order.
|
|
582
|
+
* The last layer whose subtree contains the path wins, which is what makes a
|
|
583
|
+
* narrower grant reopen a denied parent.
|
|
584
|
+
*/
|
|
585
|
+
declare function accessInLayers(target: string, layers: readonly GrantLayer[], baseline?: FileSystemAccess): FileSystemAccess;
|
|
586
|
+
/** The write grants and re-denials one policy resolves to. */
|
|
587
|
+
interface WritableRootSet {
|
|
588
|
+
/** Subtrees that end up writable, broadest first. */
|
|
589
|
+
readonly roots: readonly string[];
|
|
590
|
+
/** Subtrees inside those roots that are not writable, in application order. */
|
|
591
|
+
readonly denied: readonly string[];
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* The writable subtrees and their re-denials, flattened from {@link grantLayers}
|
|
595
|
+
* for callers that only need the two lists. Order is preserved; a narrower grant
|
|
596
|
+
* beneath a denial appears in `roots` after the denial it reopens.
|
|
597
|
+
*/
|
|
598
|
+
declare function writableRoots(policy: SandboxPolicy, options?: WritableRootOptions): WritableRootSet;
|
|
599
|
+
/** Subtrees whose contents must not be readable, for backends that can mask. */
|
|
600
|
+
declare function unreadablePaths(policy: SandboxPolicy, options?: WritableRootOptions): readonly string[];
|
|
601
|
+
//#endregion
|
|
602
|
+
//#region src/fence.d.ts
|
|
603
|
+
/**
|
|
604
|
+
* Build the fence for one policy.
|
|
605
|
+
* @param policy - the same policy the process backends receive.
|
|
606
|
+
* @param resolver - filesystem facts used to defeat symlinked paths.
|
|
607
|
+
* @param options - platform temp roots and protected-subpath behaviour.
|
|
608
|
+
*/
|
|
609
|
+
declare function createFsFence(policy: SandboxPolicy, resolver: PathResolver, options?: WritableRootOptions): FsFence;
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region src/path.d.ts
|
|
612
|
+
/**
|
|
613
|
+
* Pure, dependency-free path algebra shared by every sandbox backend.
|
|
614
|
+
*
|
|
615
|
+
* This package is Universal: it must never import `node:path`, so the lexical
|
|
616
|
+
* rules both POSIX and Win32 backends rely on live here as string operations.
|
|
617
|
+
* Filesystem-dependent resolution (realpath, existence) is injected through
|
|
618
|
+
* {@link PathResolver} by the Node-elevated provider instead.
|
|
619
|
+
*/
|
|
620
|
+
/** Which lexical dialect a path is written in. */
|
|
621
|
+
type PathFlavor = 'posix' | 'win32';
|
|
622
|
+
/** Detect the dialect of an absolute path from its own shape. */
|
|
623
|
+
declare function detectFlavor(path: string): PathFlavor;
|
|
624
|
+
/** Whether the path is absolute in either dialect. */
|
|
625
|
+
declare function isAbsolutePath(path: string): boolean;
|
|
626
|
+
/**
|
|
627
|
+
* Collapse separators and resolve `.` / `..` lexically, without touching the
|
|
628
|
+
* filesystem. A `..` that would escape the root is dropped, matching how both
|
|
629
|
+
* bwrap and Seatbelt treat an over-popped absolute path.
|
|
630
|
+
*/
|
|
631
|
+
declare function normalizePath(path: string): string;
|
|
632
|
+
/** Normalized segments below the root prefix; the root itself has none. */
|
|
633
|
+
declare function pathSegments(path: string): readonly string[];
|
|
634
|
+
/**
|
|
635
|
+
* Specificity rank used to order overlapping policy entries. A deeper path is
|
|
636
|
+
* more specific, so it is applied later and wins over a broader ancestor.
|
|
637
|
+
*/
|
|
638
|
+
declare function pathDepth(path: string): number;
|
|
639
|
+
/** Whether two paths identify the same location lexically. */
|
|
640
|
+
declare function samePath(left: string, right: string): boolean;
|
|
641
|
+
/**
|
|
642
|
+
* Whether `candidate` is `root` itself or lies beneath it. Comparison is
|
|
643
|
+
* segment-wise, so `/repo-secrets` is never treated as inside `/repo`.
|
|
644
|
+
*/
|
|
645
|
+
declare function containsPath(root: string, candidate: string): boolean;
|
|
646
|
+
/** Append relative segments to an absolute base, normalizing the result. */
|
|
647
|
+
declare function joinPath(base: string, ...parts: readonly string[]): string;
|
|
648
|
+
/** The parent of a normalized path, or `undefined` at a filesystem root. */
|
|
649
|
+
declare function parentPath(path: string): string | undefined;
|
|
650
|
+
/** Every ancestor of `path` from the filesystem root down to `path` itself. */
|
|
651
|
+
declare function ancestorPaths(path: string): readonly string[];
|
|
652
|
+
/** Drop paths already covered by a broader entry in the same list. */
|
|
653
|
+
declare function dedupeRoots(roots: readonly string[]): readonly string[];
|
|
654
|
+
//#endregion
|
|
655
|
+
//#region src/resources.d.ts
|
|
656
|
+
/**
|
|
657
|
+
* Resource limits — a third axis, and the one this package enforces weakest.
|
|
658
|
+
*
|
|
659
|
+
* A filesystem boundary can be completely correct while the host falls over: a
|
|
660
|
+
* fork storm, a growing allocation, or a loop that never ends costs nothing in
|
|
661
|
+
* file effects. Measured against the current backends, 150 processes, 2 GB of
|
|
662
|
+
* memory and 20 000 files met no resistance at all.
|
|
663
|
+
*
|
|
664
|
+
* What a host can actually promise differs so much that the promise has to be
|
|
665
|
+
* reported rather than assumed. A real quota needs cgroup v2 or a Job Object;
|
|
666
|
+
* without one, limits can still be observed and acted on, which stops a runaway
|
|
667
|
+
* but does not prevent the spike that precedes it.
|
|
668
|
+
*/
|
|
669
|
+
/** What a confined execution may consume. Every field is optional. */
|
|
670
|
+
interface ResourceLimits {
|
|
671
|
+
/** Wall-clock time before the execution is ended. */
|
|
672
|
+
readonly wallClockMs?: number;
|
|
673
|
+
/** Resident memory across the whole process tree. */
|
|
674
|
+
readonly memoryBytes?: number;
|
|
675
|
+
/** Processes in the tree, including the sandbox process itself. */
|
|
676
|
+
readonly processes?: number;
|
|
677
|
+
/** Accumulated CPU time across the tree. */
|
|
678
|
+
readonly cpuMs?: number;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* How a host enforces those limits.
|
|
682
|
+
*
|
|
683
|
+
* `quota` means the kernel refuses to exceed them. `monitor` means they are
|
|
684
|
+
* sampled and the execution is ended once exceeded — which bounds a runaway but
|
|
685
|
+
* not the spike between two samples. `none` means nothing is watching.
|
|
686
|
+
*/
|
|
687
|
+
type ResourceEnforcement = 'quota' | 'monitor' | 'none';
|
|
688
|
+
/** Why a supervised execution was ended. */
|
|
689
|
+
type ResourceBreach = 'wall-clock' | 'memory' | 'processes' | 'cpu';
|
|
690
|
+
/** What a supervised execution actually consumed. */
|
|
691
|
+
interface ResourceUsage {
|
|
692
|
+
/** Highest resident memory observed across the tree. */
|
|
693
|
+
readonly peakMemoryBytes: number;
|
|
694
|
+
/** Highest process count observed in the tree. */
|
|
695
|
+
readonly peakProcesses: number;
|
|
696
|
+
/** Highest accumulated CPU time observed. */
|
|
697
|
+
readonly cpuMs: number;
|
|
698
|
+
/** Wall-clock time the execution ran for. */
|
|
699
|
+
readonly wallClockMs: number;
|
|
700
|
+
}
|
|
701
|
+
/** Whether any limit is set at all, so a caller can skip supervision entirely. */
|
|
702
|
+
declare function hasResourceLimits(limits: ResourceLimits): boolean;
|
|
703
|
+
/**
|
|
704
|
+
* The first limit the usage exceeds, or `undefined` while it is within them.
|
|
705
|
+
* Checked in the order a runaway usually announces itself.
|
|
706
|
+
*/
|
|
707
|
+
declare function breachedLimit(usage: ResourceUsage, limits: ResourceLimits): ResourceBreach | undefined;
|
|
708
|
+
//#endregion
|
|
709
|
+
//#region src/violation.d.ts
|
|
710
|
+
/** The enforcement layer that observed a violation. */
|
|
711
|
+
type SandboxViolationBackend = 'bwrap' | 'seatbelt' | 'windows-acl' | 'fence' | 'custom';
|
|
712
|
+
/** Why a file effect was refused, normalized across backend dialects. */
|
|
713
|
+
type SandboxViolationReason = 'operation-not-permitted' | 'permission-denied' | 'read-only-filesystem' | 'policy-denied' | 'runner-failure';
|
|
714
|
+
/** One observed violation, retaining the evidence that identified it. */
|
|
715
|
+
interface SandboxViolation {
|
|
716
|
+
readonly backend: SandboxViolationBackend;
|
|
717
|
+
readonly reason: SandboxViolationReason;
|
|
718
|
+
readonly mode: string;
|
|
719
|
+
/** The path involved, when the backend named one. */
|
|
720
|
+
readonly path?: string;
|
|
721
|
+
/** Bounded evidence excerpt; never the whole output. */
|
|
722
|
+
readonly snippet: string;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Build a violation record from a classified outcome.
|
|
726
|
+
* @returns the record, or `undefined` when the outcome was not a violation.
|
|
727
|
+
*/
|
|
728
|
+
declare function sandboxViolation(classification: SandboxClassification, backend: SandboxViolationBackend, mode: string): SandboxViolation | undefined;
|
|
729
|
+
//#endregion
|
|
730
|
+
export { BASELINE_ACCESS, type CommandOutcome, type ConfinedArgv, type ConfinedSandboxMode, DEFAULT_EXEC_OUTCOMES, type ExecCapability, type ExecClassification, type ExecOutcome, type FileSystemAccess, type FileSystemEntry, type FsFence, type GrantLayer, type GrantOrigin, NETWORK_MODES, type NetworkEnforcement, type NetworkMode, PROTECTED_SUBPATHS, type PathFlavor, type PathResolver, type ResourceBreach, type ResourceEnforcement, type ResourceLimits, type ResourceUsage, type RunnerFailureRule, SANDBOX_MODES, type SandboxApproval, type SandboxApprovalGrant, type SandboxApprovalScope, type SandboxClassification, type SandboxClassificationInput, SandboxDeniedError, type SandboxEnforcement, type SandboxExecutionPolicy, type SandboxMode, type SandboxOutcomeKind, type SandboxPolicy, type SandboxPolicyDefaults, SandboxPolicyError, type SandboxPolicyRequest, type SandboxProvider, SandboxUnavailableError, type SandboxViolation, type SandboxViolationBackend, type SandboxViolationReason, type WritableRootOptions, type WritableRootSet, accessFor, accessInLayers, ancestorPaths, annotateStderr, approveSandboxEscalation, breachedLimit, classifyExec, classifyOutcome, confiningPolicy, containsPath, createFsFence, dedupeRoots, detectFlavor, entriesWithin, grantLayers, hasResourceLimits, isAbsolutePath, isConfinedMode, isNetworkMode, isSandboxApproval, isSandboxApprovalSpent, isSandboxMode, joinPath, modeAuthority, narrowNetwork, narrowPolicy, networkAuthority, normalizePath, orderEntries, parentPath, pathDepth, pathSegments, requireSandboxApproval, resolveSandboxPolicy, samePath, sandboxViolation, splitCommands, tokenizeScript, unreadablePaths, writableRoots };
|
|
731
|
+
//# sourceMappingURL=index.d.ts.map
|