@stratusagent/tool-shell 0.12.5 → 0.13.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/README.md +87 -3
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +187 -12
- package/dist/index.js.map +1 -1
- package/dist/sandbox.d.ts +131 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +531 -0
- package/dist/sandbox.js.map +1 -0
- package/package.json +38 -5
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ npm install @stratusagent/tool-shell
|
|
|
25
25
|
|
|
26
26
|
## Risk model
|
|
27
27
|
|
|
28
|
+
Under the default `approvals.posture: "open"` a `gated` call runs without asking; the column below is what each mode does with a call that still needs approval, which under `"guarded"` is every uncovered `gated` call.
|
|
29
|
+
|
|
28
30
|
| Tool | Risk | What approval mode does |
|
|
29
31
|
| --- | --- | --- |
|
|
30
32
|
| `shell.run` | `gated`, narrowed per command | `interactive` shows the command and asks; `remote` asks in Slack; `headless` runs commands inside an approved scope and refuses everything else. |
|
|
@@ -95,6 +97,88 @@ read would not have said so.
|
|
|
95
97
|
All of them can be set per agent under `agents`.
|
|
96
98
|
|
|
97
99
|
**`cwd` is a starting directory, not a jail.** An approved command can
|
|
98
|
-
change directory or name an absolute path
|
|
99
|
-
commands get approved
|
|
100
|
-
|
|
100
|
+
change directory or name an absolute path. What bounds it is the sandbox
|
|
101
|
+
below, plus which commands get approved.
|
|
102
|
+
|
|
103
|
+
## The sandbox
|
|
104
|
+
|
|
105
|
+
Every command runs under an OS sandbox that keeps it out of the Stratus home
|
|
106
|
+
and your credentials, whatever the command says:
|
|
107
|
+
|
|
108
|
+
- **Readable and writable:** the agent's workspace, its starting directory,
|
|
109
|
+
temp (on Linux a private `/tmp`, and a private one over the daemon's
|
|
110
|
+
`TMPDIR` too when that is elsewhere), and package-manager caches (`~/.npm`, `~/.cache`, `~/Library/Caches`,
|
|
111
|
+
pnpm, bun, yarn).
|
|
112
|
+
- **Readable:** the rest of the system outside your home, so system
|
|
113
|
+
toolchains work as usual, and in your home only the tools and config a
|
|
114
|
+
command needs: git config (`~/.gitconfig`, `~/.config/git`), version
|
|
115
|
+
managers and language toolchains (`~/.nvm`, `~/.volta`, `~/.fnm`,
|
|
116
|
+
`~/.bun`, `~/.deno`, `~/.rustup`, `~/.cargo`, `~/.pyenv`, `~/.rbenv`,
|
|
117
|
+
`~/.rye`, `~/.asdf`, `~/.sdkman`, `~/.gradle`, `~/.m2`, `~/.gem`, `~/go`,
|
|
118
|
+
`~/.nix-profile`, `~/.local/bin`, `~/.local/lib`, mise, uv, pnpm), plus
|
|
119
|
+
`readablePaths`.
|
|
120
|
+
- **Hidden:** the rest of your home (documents, other projects, shell
|
|
121
|
+
history, browser and app data), and any socket under it. Set
|
|
122
|
+
`home: "visible"` to make it readable again, apart from the paths below.
|
|
123
|
+
- **Not readable or writable:** the Stratus home (`~/.stratus`, or
|
|
124
|
+
`STRATUS_HOME`) apart from this agent's own workspace, which covers
|
|
125
|
+
credentials, config, souls, sessions, and other agents' workspaces, each
|
|
126
|
+
also by the real path it links to (the visible `~/Agents` or `~/Stratus`
|
|
127
|
+
folder holds the souls and workspaces the home links to). Also
|
|
128
|
+
`~/.ssh`, `~/.aws`, `~/.azure`, `~/.config/gcloud`, `~/.config/gh`, git
|
|
129
|
+
credential files, `~/.docker`, `~/.fly`, `~/.gnupg`, `~/.kube`, `~/.netrc`,
|
|
130
|
+
`~/.npmrc`, `~/.pypirc`, `~/.password-store`, `~/.config/op`, `~/.1password`,
|
|
131
|
+
1Password's group container and Secretive's container on macOS, the
|
|
132
|
+
tokens developer CLIs store after a login (Cargo's `credentials.toml`,
|
|
133
|
+
RubyGems, hub, glab, Terraform, Vault, Pulumi,
|
|
134
|
+
Maven and Gradle settings, Composer, Databricks, doctl, OCI, hcloud,
|
|
135
|
+
Claude Code's `~/.claude/.credentials.json`, Codex's `~/.codex/auth.json`), the Hugging
|
|
136
|
+
Face token under `~/.cache/huggingface`, and the macOS keychains (file and
|
|
137
|
+
service). Where the daemon's environment moves one of these stores
|
|
138
|
+
(`GH_CONFIG_DIR`, `XDG_CONFIG_HOME`, `XDG_CACHE_HOME`, `DOCKER_CONFIG`,
|
|
139
|
+
`KUBECONFIG`, `AWS_SHARED_CREDENTIALS_FILE`, `AWS_CONFIG_FILE`, `GNUPGHOME`,
|
|
140
|
+
`CLOUDSDK_CONFIG`, `AZURE_CONFIG_DIR`, `NPM_CONFIG_USERCONFIG`,
|
|
141
|
+
`PASSWORD_STORE_DIR`, `CARGO_HOME`, `PULUMI_HOME`, `TF_CLI_CONFIG_FILE`,
|
|
142
|
+
`GRADLE_USER_HOME`, `COMPOSER_HOME`, `DATABRICKS_CONFIG_FILE`,
|
|
143
|
+
`CLAUDE_CONFIG_DIR`, `CODEX_HOME`, `HF_HOME`, `HF_TOKEN_PATH`,
|
|
144
|
+
`GLAB_CONFIG_DIR`, `HUB_CONFIG`, `OP_CONFIG_DIR`), the moved location is
|
|
145
|
+
denied too, unless it is relative or holds the home or the workspace.
|
|
146
|
+
Any credential file not listed stays readable: add it to
|
|
147
|
+
`deniedPaths`. With a `workspaceRoot`, the other agents' workspaces under it;
|
|
148
|
+
a root that exists but can't be listed refuses the command.
|
|
149
|
+
- **No connection:** container runtime sockets (`/var/run/docker.sock`,
|
|
150
|
+
containerd, podman, CRI-O, BuildKit), which hand out the whole host; the
|
|
151
|
+
user's runtime directory (`$XDG_RUNTIME_DIR`, `/run/user/<uid>`) as a
|
|
152
|
+
whole, which holds the user's D-Bus and systemd manager (either can start
|
|
153
|
+
a process outside the sandbox), rootless Docker and Podman, gpg-agent and
|
|
154
|
+
systemd's ssh-agent; SSH agents, which sign with keys whose files are
|
|
155
|
+
hidden: the socket `$SSH_AUTH_SOCK` names, a `unix://` socket
|
|
156
|
+
`DOCKER_HOST` or `CONTAINER_HOST` names, launchd's session directories
|
|
157
|
+
in `/private/tmp` on macOS, 1Password's and Secretive's agent folders;
|
|
158
|
+
and any socket under a denied path. Any other local service listening on
|
|
159
|
+
a socket path stays reachable (a database in `/tmp` on macOS, a daemon
|
|
160
|
+
under `/var/run`), as does a socket in the abstract namespace.
|
|
161
|
+
- **Not writable:** everything else.
|
|
162
|
+
- **Network:** on. A command can send its own workspace somewhere, but not a
|
|
163
|
+
token it can't read.
|
|
164
|
+
|
|
165
|
+
macOS uses `sandbox-exec`. Linux uses [bubblewrap](https://github.com/containers/bubblewrap)
|
|
166
|
+
(`bwrap`), with its own pid and IPC namespaces, so a command can't signal
|
|
167
|
+
the daemon or other agents. The denied directories keep their names (`stat`
|
|
168
|
+
and directory listings of the workspace's parent directories still work, so
|
|
169
|
+
git can find its repository), but nothing can be read from inside them.
|
|
170
|
+
|
|
171
|
+
| Key | Default | What |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| `sandbox` | `required` | `required`: refuse every command when no sandbox can start (no `bwrap`, or a container that forbids user namespaces), with the reason. A host wired by hand with no workspace and no `cwd` has nothing to confine commands to, so `required` refuses there too. `auto`: run unconfined there instead, and log why, once. `off`: run with the daemon user's full access. |
|
|
174
|
+
| `deniedPaths` | none | More directories or files to hide, added to the list above, including ones inside the workspace (a repository's `.env`). A leading `~` is your home directory. |
|
|
175
|
+
| `home` | `hidden` | `hidden`: only the toolchain paths above and `readablePaths` are readable in your home. `visible`: all of it is, apart from the denied paths. |
|
|
176
|
+
| `readablePaths` | none | More paths in your home a command may read (`~/projects`). Denied paths inside them stay hidden. |
|
|
177
|
+
| `writablePaths` | none | More directories a command may write, such as a build tool's cache (`~/.gradle`). On Linux, these and the default caches are created before the command if missing, since nothing under the read-only root can be. |
|
|
178
|
+
|
|
179
|
+
All of these can be set per agent under `agents`.
|
|
180
|
+
|
|
181
|
+
A CLI that reads its login from a hidden path (`gh` from `~/.config/gh` or
|
|
182
|
+
the keychain, `fly` from `~/.fly`) can't authenticate inside the sandbox.
|
|
183
|
+
Give that agent a token through `env`, where it's visible in config, or set
|
|
184
|
+
`sandbox: "off"` for it.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type AgentWorkspaces, type JsonObject, type Plugin } from '@stratusagent/core';
|
|
1
|
+
import { type AgentWorkspaces, type JsonObject, type Plugin, type ProtectedPaths } from '@stratusagent/core';
|
|
2
2
|
import { type LocalCommandTool } from '@stratusagent/executor-local';
|
|
3
3
|
import { type TaintedWriteLedger } from '@stratusagent/plugins';
|
|
4
|
+
import { planSandbox } from './sandbox.ts';
|
|
5
|
+
export { credentialAgentEndpoints, relocatedCredentials, DEFAULT_DENIED_HOME_PATHS, DEFAULT_DENIED_SOCKETS, DEFAULT_WRITABLE_HOME_PATHS, DEFAULT_VISIBLE_HOME_PATHS, parseHomeMode, bwrapArgs, darwinProfile, planSandbox, resetSandboxProbe, stratusHomesFor, userRuntimeEndpoints, type SandboxMode, type SandboxPolicy, } from './sandbox.ts';
|
|
4
6
|
export interface ShellPluginConfig extends JsonObject {
|
|
5
7
|
/** Where commands start. A starting directory, not a jail — see the README. */
|
|
6
8
|
cwd?: string;
|
|
@@ -23,8 +25,16 @@ export interface ShellPluginConfig extends JsonObject {
|
|
|
23
25
|
* Environment variables that carry options for a command the permission
|
|
24
26
|
* engine judges by its arguments. Never passed to a child: see `settingsFor`.
|
|
25
27
|
*/
|
|
26
|
-
export declare const COMMAND_OPTION_VARIABLES: readonly ["RIPGREP_CONFIG_PATH", "GREP_OPTIONS"];
|
|
28
|
+
export declare const COMMAND_OPTION_VARIABLES: readonly ["RIPGREP_CONFIG_PATH", "GREP_OPTIONS", "GZIP"];
|
|
29
|
+
/** For tests: say the unconfined warning again. */
|
|
30
|
+
export declare const resetSandboxWarning: () => void;
|
|
27
31
|
export interface ShellToolOptions {
|
|
32
|
+
/** Where an unconfined-shell warning goes. Defaults to the plugin context's log, then stderr. */
|
|
33
|
+
warn?: (message: string) => void;
|
|
34
|
+
/** For tests: how a sandbox is planned on this host. */
|
|
35
|
+
planSandbox?: typeof planSandbox;
|
|
36
|
+
/** For tests: the platform the sandbox is prepared for. Defaults to this one. */
|
|
37
|
+
platform?: NodeJS.Platform;
|
|
28
38
|
/** The environment to grant *from*. Defaults to the daemon's. */
|
|
29
39
|
processEnv?: NodeJS.ProcessEnv;
|
|
30
40
|
/**
|
|
@@ -33,6 +43,12 @@ export interface ShellToolOptions {
|
|
|
33
43
|
* supplies one or leaves the cwd to `workspaceRoot`.
|
|
34
44
|
*/
|
|
35
45
|
workspaces?: AgentWorkspaces;
|
|
46
|
+
/**
|
|
47
|
+
* What the host protects, `PluginContext.protectedPaths`: the sandbox
|
|
48
|
+
* hides each of these by its real path as well as its name. The plugin
|
|
49
|
+
* passes its `setup` context's seam through.
|
|
50
|
+
*/
|
|
51
|
+
protectedPaths?: ProtectedPaths;
|
|
36
52
|
/** What `~` in `cwd` expands to. Defaults to the daemon user's home. */
|
|
37
53
|
home?: string;
|
|
38
54
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,EAEf,KAAK,MAAM,EACX,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAQL,WAAW,EAMZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,EACzB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AAUtB,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,6CAA6C;IAC7C,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA8BD;;;GAGG;AAIH,eAAO,MAAM,wBAAwB,0DAA2D,CAAC;AAyRjG,mDAAmD;AACnD,eAAO,MAAM,mBAAmB,QAAO,IAEtC,CAAC;AAmCF,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,WAAW,CAAC;IACjC,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AA0CD,eAAO,MAAM,eAAe,GAAI,SAAQ,UAAe,EAAE,UAAS,gBAAqB,KAAG,gBAyIzF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAQ,UAAe,EAAE,UAAS,gBAAqB,KAAG,MAwB1F,CAAC;AAEH,4DAA4D;AAC5D,eAAO,MAAM,YAAY,YA3BiB,UAAU,YAAgB,gBAAgB,KAAQ,MA2B/C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
1
2
|
import { mkdir, stat } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
2
4
|
import path from 'node:path';
|
|
3
5
|
import { DEFAULT_SUBPROCESS_PASS_ENV, leastTrusted, } from '@stratusagent/core';
|
|
4
6
|
import { defineLocalCommandTool, LOCAL_COMMAND_MAX_TIMEOUT_MS, } from '@stratusagent/executor-local';
|
|
5
|
-
import { createFileLedger, expandHome, resolvePluginAgentConfig, workspacePreparer, workspaceResolver, } from '@stratusagent/plugins';
|
|
7
|
+
import { allAgentWorkspaces, createFileLedger, expandHome, resolvePluginAgentConfig, workspacePreparer, workspaceResolver, } from '@stratusagent/plugins';
|
|
8
|
+
import { relocatedCredentials, credentialAgentEndpoints, DEFAULT_DENIED_HOME_PATHS, DEFAULT_DENIED_SOCKETS, parseHomeMode, parseSandboxMode, DEFAULT_VISIBLE_HOME_PATHS, planSandbox, spellings, stratusHomesFor, userRuntimeEndpoints, writableHomePathsFor, } from "./sandbox.js";
|
|
9
|
+
export { credentialAgentEndpoints, relocatedCredentials, DEFAULT_DENIED_HOME_PATHS, DEFAULT_DENIED_SOCKETS, DEFAULT_WRITABLE_HOME_PATHS, DEFAULT_VISIBLE_HOME_PATHS, parseHomeMode, bwrapArgs, darwinProfile, planSandbox, resetSandboxProbe, stratusHomesFor, userRuntimeEndpoints, } from "./sandbox.js";
|
|
6
10
|
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
11
|
const DEFAULT_MAX_OUTPUT_BYTES = 100_000;
|
|
8
12
|
// What the child is allowed to inherit by name — the kernel's one list,
|
|
@@ -37,7 +41,7 @@ const maxOutputBytesFor = (config, session) => asNumber(resolvePluginAgentConfig
|
|
|
37
41
|
// Not POSIXLY_CORRECT: macOS's /bin/sh exports it to every command it runs,
|
|
38
42
|
// so the permission engine reads arguments both ways instead (see
|
|
39
43
|
// `operandsToo` in @stratusagent/permissions).
|
|
40
|
-
export const COMMAND_OPTION_VARIABLES = ['RIPGREP_CONFIG_PATH', 'GREP_OPTIONS'];
|
|
44
|
+
export const COMMAND_OPTION_VARIABLES = ['RIPGREP_CONFIG_PATH', 'GREP_OPTIONS', 'GZIP'];
|
|
41
45
|
/**
|
|
42
46
|
* Flags that stop a shell from running its user startup files before the
|
|
43
47
|
* command. Without them zsh sources `$HOME/.zshenv`, tcsh and csh
|
|
@@ -65,8 +69,16 @@ const startupOff = (shell) => {
|
|
|
65
69
|
const GIT_REPOSITORY_VARIABLES = [
|
|
66
70
|
'GIT_DIR', 'GIT_WORK_TREE', 'GIT_COMMON_DIR', 'GIT_INDEX_FILE', 'GIT_OBJECT_DIRECTORY', 'GIT_ALTERNATE_OBJECT_DIRECTORIES', 'GIT_NAMESPACE',
|
|
67
71
|
];
|
|
68
|
-
/**
|
|
69
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Variables that make a shell run code before the command, or read it
|
|
74
|
+
* differently from the permission engine. Never passed. `CDPATH` sends a
|
|
75
|
+
* relative `cd` somewhere other than the working directory the engine
|
|
76
|
+
* follows it from. `BASHOPTS`, `SHELLOPTS` and `POSIXLY_CORRECT` switch on
|
|
77
|
+
* shell options at startup (`cdable_vars` makes `cd HOME` follow `$HOME`).
|
|
78
|
+
*/
|
|
79
|
+
const SHELL_STARTUP_VARIABLES = [
|
|
80
|
+
'BASH_ENV', 'ENV', 'ZDOTDIR', 'CDPATH', 'BASHOPTS', 'SHELLOPTS', 'POSIXLY_CORRECT',
|
|
81
|
+
];
|
|
70
82
|
const settingsFor = (config, session, env, workspaces, home) => {
|
|
71
83
|
// `env` merges rather than replacing: an agent given its own token keeps
|
|
72
84
|
// the fleet's PATH (#205). A `null` withholds a shared variable from one
|
|
@@ -112,7 +124,8 @@ const settingsFor = (config, session, env, workspaces, home) => {
|
|
|
112
124
|
}
|
|
113
125
|
// Variables that hand a judged command options the command line never
|
|
114
126
|
// shows: `rg pattern` with RIPGREP_CONFIG_PATH can be `rg --pre … --follow
|
|
115
|
-
// pattern`,
|
|
127
|
+
// pattern`, BSD grep reads GREP_OPTIONS, and gzip reads GZIP (`-S x`
|
|
128
|
+
// names an output file no operand does). The permission engine judges
|
|
116
129
|
// the command as written, so what it judges has to be what runs. Withheld
|
|
117
130
|
// whatever the config says.
|
|
118
131
|
for (const name of COMMAND_OPTION_VARIABLES) {
|
|
@@ -132,14 +145,15 @@ const settingsFor = (config, session, env, workspaces, home) => {
|
|
|
132
145
|
// empty) resolve to the working directory, which is the workspace. Kept
|
|
133
146
|
// out, whatever env or passEnv says; the system's own paths are unchanged.
|
|
134
147
|
if (typeof granted.PATH === 'string') {
|
|
148
|
+
// Compared as written and through symlinks on both sides: a workspace
|
|
149
|
+
// reached by an alias, or a PATH entry that is one, is the same directory.
|
|
135
150
|
const owned = [cwd, workspaceResolver(workspaces, workspaceRoot)?.(session.agent.id)]
|
|
136
|
-
.filter((dir) => typeof dir === 'string' && dir.length > 0)
|
|
151
|
+
.filter((dir) => typeof dir === 'string' && dir.length > 0)
|
|
152
|
+
.flatMap((dir) => [path.resolve(dir), canonicalPath(dir)]);
|
|
137
153
|
granted.PATH = granted.PATH
|
|
138
154
|
.split(':')
|
|
139
|
-
.filter((entry) => entry.length > 0 && path.isAbsolute(entry)
|
|
140
|
-
|
|
141
|
-
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
142
|
-
}))
|
|
155
|
+
.filter((entry) => entry.length > 0 && path.isAbsolute(entry)
|
|
156
|
+
&& ![path.resolve(entry), canonicalPath(entry)].some((candidate) => owned.some((dir) => isWithin(dir, candidate))))
|
|
143
157
|
.join(':');
|
|
144
158
|
// An empty PATH is the current directory to `sh`, the one thing this
|
|
145
159
|
// filter exists to keep out.
|
|
@@ -163,7 +177,162 @@ const settingsFor = (config, session, env, workspaces, home) => {
|
|
|
163
177
|
timeoutMs: asNumber(resolved.timeoutMs, DEFAULT_TIMEOUT_MS),
|
|
164
178
|
maxOutputBytes: asNumber(resolved.maxOutputBytes, DEFAULT_MAX_OUTPUT_BYTES),
|
|
165
179
|
shell: typeof resolved.shell === 'string' && resolved.shell.length > 0 ? resolved.shell : '/bin/sh',
|
|
180
|
+
sandbox: parseSandboxMode(resolved.sandbox),
|
|
181
|
+
home: parseHomeMode(resolved.home),
|
|
182
|
+
// The agent's own workspace, whatever cwd says: it is what the sandbox
|
|
183
|
+
// leaves writable inside a Stratus home it otherwise hides.
|
|
184
|
+
workspace: workspaceResolver(workspaces, workspaceRoot)?.(session.agent.id),
|
|
185
|
+
// Creates it (owner-only, through the host) for the sandbox to bind.
|
|
186
|
+
// Only needed when a configured cwd won: otherwise the cwd *is* the
|
|
187
|
+
// prepared workspace, and it is prepared once per call.
|
|
188
|
+
prepareWorkspace: configuredCwd !== undefined && workspaceFor ? () => workspaceFor(session.agent.id) : undefined,
|
|
189
|
+
workspaceRoot,
|
|
190
|
+
deniedPaths: asStrings(resolved.deniedPaths, []).map((entry) => expandHome(entry, home)),
|
|
191
|
+
writablePaths: asStrings(resolved.writablePaths, []).map((entry) => expandHome(entry, home)),
|
|
192
|
+
readablePaths: asStrings(resolved.readablePaths, []).map((entry) => expandHome(entry, home)),
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* The command to spawn for `shell shellArgs…`, under the sandbox unless the
|
|
197
|
+
* operator turned it off. `required` refuses when no sandbox can start;
|
|
198
|
+
* `auto` runs unconfined then, after saying so once per process.
|
|
199
|
+
*/
|
|
200
|
+
const sandboxed = async (settings, shellArgs, options) => {
|
|
201
|
+
const unconfined = { command: settings.shell, args: shellArgs };
|
|
202
|
+
if (settings.sandbox === 'off') {
|
|
203
|
+
return unconfined;
|
|
204
|
+
}
|
|
205
|
+
// With no workspace from the host and no configured cwd there is nothing
|
|
206
|
+
// bounded to confine commands to. The process directory is not one: it
|
|
207
|
+
// can be a home, `/`, or a repository whose node_modules/.bin is on PATH.
|
|
208
|
+
const workspace = settings.workspace ?? settings.cwd;
|
|
209
|
+
if (workspace === undefined) {
|
|
210
|
+
if (settings.sandbox === 'required') {
|
|
211
|
+
throw new Error('shell.run refused: commands must run sandboxed (sandbox: "required"), but this agent has no workspace to confine commands to. '
|
|
212
|
+
+ 'Set cwd for @stratusagent/tool-shell to the directory commands may write, or set sandbox to "auto" or "off" to run them unconfined.');
|
|
213
|
+
}
|
|
214
|
+
warnUnconfined(options, 'this agent has no workspace to confine commands to');
|
|
215
|
+
return unconfined;
|
|
216
|
+
}
|
|
217
|
+
const userHome = options.home ?? os.homedir();
|
|
218
|
+
const processEnv = options.processEnv ?? process.env;
|
|
219
|
+
const platform = options.platform ?? process.platform;
|
|
220
|
+
// The workspace is bound into the sandbox, and bwrap refuses a source
|
|
221
|
+
// that does not exist; a configured cwd means nothing prepared it yet.
|
|
222
|
+
if (settings.workspace !== undefined && settings.prepareWorkspace) {
|
|
223
|
+
await mkdir(settings.prepareWorkspace(), { recursive: true });
|
|
224
|
+
}
|
|
225
|
+
// What the host protects (its home, the credential files, every soul) and
|
|
226
|
+
// every other agent's workspace, each also by its real path: in the
|
|
227
|
+
// surfaced layout those are links into a visible folder (`~/Stratus/<id>/`)
|
|
228
|
+
// that hiding the home by name leaves readable.
|
|
229
|
+
const own = new Set(spellings(workspace));
|
|
230
|
+
// A configured `workspaceRoot` puts every agent's workspace under it,
|
|
231
|
+
// outside the host's seam, so its other entries are listed from disk.
|
|
232
|
+
// Listed the way every guard lists them: a root that is not there holds
|
|
233
|
+
// no siblings, and any other failure (EACCES, EMFILE) fails the call,
|
|
234
|
+
// since an empty list would leave every sibling readable.
|
|
235
|
+
const underRoot = settings.workspaceRoot === undefined
|
|
236
|
+
? []
|
|
237
|
+
: await allAgentWorkspaces(undefined, settings.workspaceRoot);
|
|
238
|
+
const others = [...await options.workspaces?.all() ?? [], ...underRoot]
|
|
239
|
+
.filter((dir) => !spellings(dir).some((spelling) => own.has(spelling)));
|
|
240
|
+
const hostProtected = await options.protectedPaths?.all() ?? [];
|
|
241
|
+
const policy = {
|
|
242
|
+
workspace,
|
|
243
|
+
...(settings.cwd && settings.cwd !== workspace ? { cwd: settings.cwd } : {}),
|
|
244
|
+
denied: [...new Set([
|
|
245
|
+
...stratusHomesFor(workspace, processEnv, userHome),
|
|
246
|
+
...hostProtected,
|
|
247
|
+
...others,
|
|
248
|
+
...DEFAULT_DENIED_HOME_PATHS.map((entry) => path.join(userHome, entry)),
|
|
249
|
+
...DEFAULT_DENIED_SOCKETS,
|
|
250
|
+
...userRuntimeEndpoints(processEnv, process.getuid?.()),
|
|
251
|
+
...credentialAgentEndpoints(processEnv, platform),
|
|
252
|
+
...relocatedCredentials(processEnv, userHome, workspace),
|
|
253
|
+
...settings.deniedPaths,
|
|
254
|
+
].flatMap(spellings))],
|
|
255
|
+
writable: [
|
|
256
|
+
...writableHomePathsFor(platform).map((entry) => path.join(userHome, entry)),
|
|
257
|
+
...settings.writablePaths,
|
|
258
|
+
],
|
|
259
|
+
tmp: os.tmpdir(),
|
|
260
|
+
...(settings.home === 'hidden' ? {
|
|
261
|
+
home: {
|
|
262
|
+
path: userHome,
|
|
263
|
+
visible: [...new Set([
|
|
264
|
+
...DEFAULT_VISIBLE_HOME_PATHS.map((entry) => path.join(userHome, entry)),
|
|
265
|
+
...writableHomePathsFor(platform).map((entry) => path.join(userHome, entry)),
|
|
266
|
+
...settings.readablePaths,
|
|
267
|
+
])],
|
|
268
|
+
},
|
|
269
|
+
} : {}),
|
|
166
270
|
};
|
|
271
|
+
// bwrap binds only what exists, under a read-only root, so a cache
|
|
272
|
+
// missing now could never be created by the command. macOS's profile
|
|
273
|
+
// allows creating it, so nothing is made there ahead of use.
|
|
274
|
+
if (platform === 'linux') {
|
|
275
|
+
for (const dir of policy.writable) {
|
|
276
|
+
await mkdir(dir, { recursive: true }).catch(() => undefined);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const plan = (options.planSandbox ?? planSandbox)(policy, settings.shell, shellArgs);
|
|
280
|
+
if (plan.kind === 'sandboxed') {
|
|
281
|
+
return plan.command;
|
|
282
|
+
}
|
|
283
|
+
if (settings.sandbox === 'required') {
|
|
284
|
+
throw new Error(`shell.run refused: commands must run sandboxed (sandbox: "required"), and ${plan.reason}. `
|
|
285
|
+
+ 'Fix that, or set sandbox to "off" for @stratusagent/tool-shell to run commands with the daemon user\'s full access.');
|
|
286
|
+
}
|
|
287
|
+
warnUnconfined(options, plan.reason);
|
|
288
|
+
return unconfined;
|
|
289
|
+
};
|
|
290
|
+
/** The one line `auto` owes before running unconfined, once per process. */
|
|
291
|
+
const warnUnconfined = (options, reason) => {
|
|
292
|
+
if (unconfinedWarned) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
unconfinedWarned = true;
|
|
296
|
+
(options.warn ?? ((message) => process.stderr.write(`${message}\n`)))(`tool-shell: commands run without a sandbox because ${reason}; they can read the Stratus home and your credentials. `
|
|
297
|
+
+ 'Set sandbox to "required" to refuse instead, or "off" to silence this.');
|
|
298
|
+
};
|
|
299
|
+
let unconfinedWarned = false;
|
|
300
|
+
/** For tests: say the unconfined warning again. */
|
|
301
|
+
export const resetSandboxWarning = () => {
|
|
302
|
+
unconfinedWarned = false;
|
|
303
|
+
};
|
|
304
|
+
const isWithin = (dir, candidate) => {
|
|
305
|
+
const relative = path.relative(dir, candidate);
|
|
306
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* Where a path really is, symlinks resolved. Walked one component at a time
|
|
310
|
+
* in the order the kernel does: a symlink is followed before the `..` after
|
|
311
|
+
* it, so `/alias/../bin` lands beside the link's target, not beside the link
|
|
312
|
+
* (collapsing `..` first would get that wrong). A path that does not exist
|
|
313
|
+
* yet resolves through its nearest existing ancestor, so a `bin` the agent
|
|
314
|
+
* could still create under an aliased workspace is placed where it would land.
|
|
315
|
+
*/
|
|
316
|
+
const canonicalPath = (target) => {
|
|
317
|
+
const parts = (path.isAbsolute(target) ? target : `${process.cwd()}/${target}`).split('/');
|
|
318
|
+
let current = '/';
|
|
319
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
320
|
+
const part = parts[index];
|
|
321
|
+
if (part === '' || part === '.')
|
|
322
|
+
continue;
|
|
323
|
+
if (part === '..') {
|
|
324
|
+
current = path.dirname(current);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
const next = path.join(current, part);
|
|
328
|
+
try {
|
|
329
|
+
current = realpathSync(next);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
return path.join(next, ...parts.slice(index + 1));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return current;
|
|
167
336
|
};
|
|
168
337
|
/**
|
|
169
338
|
* The label a command's output can carry, given what this agent has on
|
|
@@ -270,9 +439,11 @@ export const createShellTool = (config = {}, options = {}) => {
|
|
|
270
439
|
}
|
|
271
440
|
}
|
|
272
441
|
}
|
|
442
|
+
const shellArgs = [...startupOff(settings.shell), '-c', command];
|
|
443
|
+
const run = await sandboxed(settings, shellArgs, options);
|
|
273
444
|
return {
|
|
274
|
-
command:
|
|
275
|
-
args:
|
|
445
|
+
command: run.command,
|
|
446
|
+
args: run.args,
|
|
276
447
|
...(settings.cwd ? { cwd: settings.cwd } : {}),
|
|
277
448
|
env: settings.env,
|
|
278
449
|
// Required, not preferred. The daemon's environment holds every key
|
|
@@ -355,8 +526,12 @@ export const createShellPlugin = (config = {}, options = {}) => ({
|
|
|
355
526
|
const ledgerFor = options.ledger === undefined && context.workspaces !== undefined
|
|
356
527
|
? workspaceResolver(context.workspaces, undefined)
|
|
357
528
|
: undefined;
|
|
529
|
+
const warn = options.warn ?? context.log;
|
|
530
|
+
const protectedPaths = options.protectedPaths ?? context.protectedPaths;
|
|
358
531
|
context.tools.register(createShellTool(config, {
|
|
359
532
|
...options,
|
|
533
|
+
...(protectedPaths !== undefined ? { protectedPaths } : {}),
|
|
534
|
+
...(warn !== undefined ? { warn } : {}),
|
|
360
535
|
...(workspaces !== undefined ? { workspaces } : {}),
|
|
361
536
|
...(ledgerFor !== undefined ? { ledger: createFileLedger(ledgerFor) } : {}),
|
|
362
537
|
}));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,2BAA2B,EAC3B,YAAY,GAQb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAI7B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,GAElB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EACtB,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,WAAW,EACX,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,EACzB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GAGrB,MAAM,cAAc,CAAC;AAEtB,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAEzC,wEAAwE;AACxE,uEAAuE;AACvE,sEAAsE;AACtE,MAAM,gBAAgB,GAAG,CAAC,GAAG,2BAA2B,CAAC,CAAC;AAqB1D,MAAM,QAAQ,GAAG,CAAC,KAA4B,EAAE,QAAgB,EAAU,EAAE,CAC1E,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAEtF,MAAM,SAAS,GAAG,CAAC,KAA4B,EAAE,QAAkB,EAAY,EAAE,CAC/E,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAExG,qEAAqE;AACrE,0EAA0E;AAC1E,0EAA0E;AAC1E,gEAAgE;AAChE,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAE,OAAgB,EAAwC,EAAE;IAC3G,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,2BAA2B,QAAQ,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC3G,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG,CAAC,MAAkB,EAAE,OAAgB,EAAU,EAAE,CACzE,QAAQ,CAAC,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAC;AAExG;;;GAGG;AACH,4EAA4E;AAC5E,kEAAkE;AAClE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,qBAAqB,EAAE,cAAc,EAAE,MAAM,CAAU,CAAC;AAEjG;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAC,KAAa,EAAY,EAAE;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,wCAAwC;IACxC,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,aAAa,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,wBAAwB,GAAsB;IAClD,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,eAAe;CAC5I,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,uBAAuB,GAAsB;IACjD,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB;CACnF,CAAC;AAEF,MAAM,WAAW,GAAG,CAClB,MAAkB,EAClB,OAAgB,EAChB,GAAsB,EACtB,UAAuC,EACvC,IAAwB,EACxB,EAAE;IACF,yEAAyE;IACzE,yEAAyE;IACzE,2CAA2C;IAC3C,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5F,MAAM,aAAa,GAAG,OAAO,QAAQ,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IACtG,yEAAyE;IACzE,yEAAyE;IACzE,qEAAqE;IACrE,yCAAyC;IACzC,MAAM,aAAa,GAAG,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC;QAC/E,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;QAChC,CAAC,CAAC,SAAS,CAAC;IACd,uEAAuE;IACvE,yEAAyE;IACzE,wEAAwE;IACxE,wDAAwD;IACxD,oEAAoE;IACpE,sEAAsE;IACtE,MAAM,YAAY,GAAG,iBAAiB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,aAAa,IAAI,YAAY,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACjE,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC;IAC9B,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACxB,CAAC;iBAAM,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC1B,kEAAkE;gBAClE,+DAA+D;gBAC/D,iEAAiE;gBACjE,0CAA0C;gBAC1C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,2EAA2E;IAC3E,qEAAqE;IACrE,sEAAsE;IACtE,0EAA0E;IAC1E,4BAA4B;IAC5B,KAAK,MAAM,IAAI,IAAI,wBAAwB,EAAE,CAAC;QAC5C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,wEAAwE;IACxE,wEAAwE;IACxE,uEAAuE;IACvE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,IAAI,uBAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,wBAAwB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACvH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,mEAAmE;IACnE,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,sEAAsE;QACtE,2EAA2E;QAC3E,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,iBAAiB,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aAClF,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;aACzE,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;aACxB,KAAK,CAAC,GAAG,CAAC;aACV,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;eACxD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;aACpH,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,qEAAqE;QACrE,6BAA6B;QAC7B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,GAAG,eAAe,CAAC;QACjC,CAAC;IACH,CAAC;IACD,sEAAsE;IACtE,yEAAyE;IACzE,mEAAmE;IACnE,sEAAsE;IACtE,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC;IAC5B,OAAO,CAAC,mBAAmB,GAAG,MAAM,CAAC;IACrC,OAAO;QACL,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,uEAAuE;QACvE,wEAAwE;QACxE,4CAA4C;QAC5C,OAAO,EAAE,aAAa,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS;QACzD,GAAG,EAAE,OAAO;QACZ,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;QAC3D,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,wBAAwB,CAAC;QAC3E,KAAK,EAAE,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QACnG,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC;QAC3C,IAAI,EAAE,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;QAClC,uEAAuE;QACvE,4DAA4D;QAC5D,SAAS,EAAE,iBAAiB,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3E,qEAAqE;QACrE,oEAAoE;QACpE,wDAAwD;QACxD,gBAAgB,EAAE,aAAa,KAAK,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QAChH,aAAa;QACb,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACxF,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5F,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;KAC7F,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,SAAS,GAAG,KAAK,EACrB,QAAwC,EACxC,SAAmB,EACnB,OAAyB,EACqB,EAAE;IAChD,MAAM,UAAU,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAChE,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC/B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,yEAAyE;IACzE,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC;IACrD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,QAAQ,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,gIAAgI;kBAC9H,qIAAqI,CACxI,CAAC;QACJ,CAAC;QACD,cAAc,CAAC,OAAO,EAAE,oDAAoD,CAAC,CAAC;QAC9E,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;IAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACtD,sEAAsE;IACtE,uEAAuE;IACvE,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAClE,MAAM,KAAK,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,0EAA0E;IAC1E,oEAAoE;IACpE,4EAA4E;IAC5E,gDAAgD;IAChD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1C,sEAAsE;IACtE,sEAAsE;IACtE,wEAAwE;IACxE,sEAAsE;IACtE,0DAA0D;IAC1D,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,KAAK,SAAS;QACpD,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,MAAM,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,SAAS,CAAC;SACpE,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IAChE,MAAM,MAAM,GAAkB;QAC5B,SAAS;QACT,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC;gBAClB,GAAG,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC;gBACnD,GAAG,aAAa;gBAChB,GAAG,MAAM;gBACT,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACvE,GAAG,sBAAsB;gBACzB,GAAG,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACvD,GAAG,wBAAwB,CAAC,UAAU,EAAE,QAAQ,CAAC;gBACjD,GAAG,oBAAoB,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC;gBACxD,GAAG,QAAQ,CAAC,WAAW;aACxB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QACtB,QAAQ,EAAE;YACR,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC5E,GAAG,QAAQ,CAAC,aAAa;SAC1B;QACD,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE;QAChB,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC;wBACnB,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;wBACxE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;wBAC5E,GAAG,QAAQ,CAAC,aAAa;qBAC1B,CAAC,CAAC;aACJ;SACF,CAAC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,mEAAmE;IACnE,qEAAqE;IACrE,6DAA6D;IAC7D,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,WAAW,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACrF,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,6EAA6E,IAAI,CAAC,MAAM,IAAI;cAC1F,qHAAqH,CACxH,CAAC;IACJ,CAAC;IACD,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF,4EAA4E;AAC5E,MAAM,cAAc,GAAG,CAAC,OAAyB,EAAE,MAAc,EAAQ,EAAE;IACzE,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO;IACT,CAAC;IACD,gBAAgB,GAAG,IAAI,CAAC;IACxB,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAC3E,sDAAsD,MAAM,yDAAyD;UACnH,wEAAwE,CAC3E,CAAC;AACJ,CAAC,CAAC;AAEF,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B,mDAAmD;AACnD,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAS,EAAE;IAC5C,gBAAgB,GAAG,KAAK,CAAC;AAC3B,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,SAAiB,EAAW,EAAE;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/C,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,aAAa,GAAG,CAAC,MAAc,EAAU,EAAE;IAC/C,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3F,IAAI,OAAO,GAAG,GAAG,CAAC;IAClB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAE,CAAC;QAC3B,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,GAAG;YAAE,SAAS;QAC1C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAiCF;;;;;;;;;;;;;GAaG;AACH,MAAM,aAAa,GAAG,KAAK,EAAE,MAA0B,EAAE,OAAe,EAAuB,EAAE;IAC/F,0EAA0E;IAC1E,0EAA0E;IAC1E,wEAAwE;IACxE,qEAAqE;IACrE,sEAAsE;IACtE,kEAAkE;IAClE,IAAI,KAAgD,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAClC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YACxB,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,EAAE;gBACjC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC,CAAC;YACvE,CAAC,CAAC;SACH,CAAC,CAAC;QACH,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC,CAAC;AAEF,sFAAsF;AACtF,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,SAAqB,EAAE,EAAE,UAA4B,EAAE,EAAoB,EAAE;IAC3G,MAAM,IAAI,GAAG,sBAAsB,CAAC;QAClC,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,8EAA8E;QAC3F,qEAAqE;QACrE,qEAAqE;QACrE,oEAAoE;QACpE,uEAAuE;QACvE,wEAAwE;QACxE,sEAAsE;QACtE,sEAAsE;QACtE,uEAAuE;QACvE,qEAAqE;QACrE,mCAAmC;QACnC,WAAW,EAAE,SAAS;QACtB,wEAAwE;QACxE,uEAAuE;QACvE,mEAAmE;QACnE,qDAAqD;QACrD,IAAI,EAAE,OAAO;QACb,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;gBACpE,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,+DAA+D;oBAC/D,kEAAkE;oBAClE,4DAA4D;oBAC5D,WAAW,EAAE,gEAAgE;0BACzE,wBAAwB,4BAA4B,KAAK,4BAA4B,GAAG,MAAM,kFAAkF;0BAChL,gGAAgG;0BAChG,mEAAmE;iBACxE;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;SACtB;QACD,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO;YACzC,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC1C,CAAC;YACD,qEAAqE;YACrE,qEAAqE;YACrE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,OAAO,EAAE,SAAS,EAAE,CAAC,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9E,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAC1B,MAAM,EACN,OAAO,EACP,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EACjC,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,IAAI,CACb,CAAC;YACF,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;gBACjB,iEAAiE;gBACjE,iEAAiE;gBACjE,8DAA8D;gBAC9D,mEAAmE;gBACnE,+DAA+D;gBAC/D,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;oBACrB,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACjD,CAAC;qBAAM,CAAC;oBACN,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;oBACxF,IAAI,CAAC,MAAM,EAAE,CAAC;wBACZ,MAAM,IAAI,KAAK,CACb,oDAAoD,QAAQ,CAAC,GAAG,IAAI;8BAClE,wDAAwD,CAC3D,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM,SAAS,GAAG,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACjE,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YAC1D,OAAO;gBACL,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,GAAG,EAAE,QAAQ,CAAC,GAAG;gBACjB,oEAAoE;gBACpE,oEAAoE;gBACpE,iEAAiE;gBACjE,wCAAwC;gBACxC,OAAO,EAAE,SAAS;gBAClB,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;gBACxD,mEAAmE;gBACnE,kEAAkE;gBAClE,+CAA+C;gBAC/C,cAAc,EAAE,QAAQ,CAAC,cAAc;aACxC,CAAC;QACJ,CAAC;QACD,mEAAmE;QACnE,uEAAuE;QACvE,qEAAqE;QACrE,8DAA8D;QAC9D,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS;YAC9B,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;YACzF,CAAC,CAAC,EAAE,CAAC;QACP,WAAW,CAAC,MAA6B,EAAE,OAAO;YAChD,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;YAC/E,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;YAC/E,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,IAAI;gBACnB,MAAM,EAAE,MAAM,CAAC,IAAI;gBACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS;gBAC/C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1C,UAAU,EAAE,MAAM,CAAC,UAAU;aAC9B,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,IAAI;QACP;;;;;;;;WAQG;QACH,UAAU,EAAE,CAAC,KAAiB,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACzG,yEAAyE;QACzE,qEAAqE;QACrE,qDAAqD;QACrD,MAAM,EAAE,CAAC,OAAgB,EAAE,EAAE;YAC3B,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC5F,IAAI,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChE,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,aAAa,GAAG,OAAO,QAAQ,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YACtG,OAAO,iBAAiB,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAqB,EAAE,EAAE,UAA4B,EAAE,EAAU,EAAE,CAAC,CAAC;IACrG,IAAI,EAAE,0BAA0B;IAChC,KAAK,CAAC,OAAO;QACX,kEAAkE;QAClE,sEAAsE;QACtE,6CAA6C;QAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;QAC5D,mEAAmE;QACnE,wEAAwE;QACxE,sEAAsE;QACtE,gDAAgD;QAChD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;YAChF,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC;YAClD,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;QACzC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC;QACxE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE;YAC7C,GAAG,OAAO;YACV,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC,CAAC,CAAC;IACN,CAAC;CACF,CAAC,CAAC;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeps an agent-composed command out of the daemon's home and the user's
|
|
3
|
+
* secrets, whatever the command says.
|
|
4
|
+
*
|
|
5
|
+
* The permission engine judges what a command *says*; this bounds what it
|
|
6
|
+
* can *do*. A command runs with the workspace writable, the rest of the
|
|
7
|
+
* system readable, and these unreadable: the Stratus home outside the
|
|
8
|
+
* agent's own workspace (credentials, config, other agents, sessions), and
|
|
9
|
+
* the usual places a user keeps credentials. The network is left on: an
|
|
10
|
+
* agent that works needs `git push` and `npm install`, and what it can send
|
|
11
|
+
* is its own workspace, not a token.
|
|
12
|
+
*
|
|
13
|
+
* macOS uses `sandbox-exec` with a generated profile; Linux uses `bwrap`
|
|
14
|
+
* (bubblewrap). Neither falls back silently: under `required` (the
|
|
15
|
+
* default) an unavailable sandbox refuses the command, and under `auto` it
|
|
16
|
+
* runs unconfined only after saying so once.
|
|
17
|
+
*/
|
|
18
|
+
export type SandboxMode = 'auto' | 'required' | 'off';
|
|
19
|
+
/** Paths under the user's home that hold credentials, refused to every sandboxed command. */
|
|
20
|
+
export declare const DEFAULT_DENIED_HOME_PATHS: readonly string[];
|
|
21
|
+
/**
|
|
22
|
+
* Control sockets of container runtimes. A read-only view of a socket still
|
|
23
|
+
* accepts a connection, and any of these hands out the whole host (`docker
|
|
24
|
+
* run -v /:/host`), so they are refused like the credential stores. Docker
|
|
25
|
+
* Desktop's own socket lives under `~/.docker`, which is denied already.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_DENIED_SOCKETS: readonly string[];
|
|
28
|
+
/**
|
|
29
|
+
* The user's runtime directories, `$XDG_RUNTIME_DIR` and `/run/user/<uid>`,
|
|
30
|
+
* denied whole. Everything there is a per-user service endpoint: D-Bus and
|
|
31
|
+
* the systemd manager (either starts a same-user process outside the
|
|
32
|
+
* sandbox), rootless Docker and Podman, gpg-agent and systemd's ssh-agent
|
|
33
|
+
* (either signs with keys whose files are hidden). Naming entries one by
|
|
34
|
+
* one kept missing the next one. An abstract-namespace socket has no path
|
|
35
|
+
* to cover; the network is not unshared, so one listening there stays
|
|
36
|
+
* reachable.
|
|
37
|
+
*/
|
|
38
|
+
export declare const userRuntimeEndpoints: (processEnv: NodeJS.ProcessEnv, uid: number | undefined) => string[];
|
|
39
|
+
/**
|
|
40
|
+
* The credential stores, and container sockets, that the daemon's
|
|
41
|
+
* environment moves elsewhere. A relative value is ignored (it names no
|
|
42
|
+
* fixed place), and so is one that is or holds the user's home or the
|
|
43
|
+
* workspace: denying it would hide the whole system or the agent's own work,
|
|
44
|
+
* and the home's own credential paths are denied by name already.
|
|
45
|
+
*/
|
|
46
|
+
export declare const relocatedCredentials: (processEnv: NodeJS.ProcessEnv, userHome: string, workspace: string) => string[];
|
|
47
|
+
/**
|
|
48
|
+
* SSH agent sockets outside the home and runtime directory: the one
|
|
49
|
+
* `$SSH_AUTH_SOCK` names, and on macOS every launchd session directory in
|
|
50
|
+
* `/private/tmp` (launchd's own agent listens in one, under a random name a
|
|
51
|
+
* command can list). `/private/tmp` is otherwise writable to the command;
|
|
52
|
+
* Linux gives it a private `/tmp` already.
|
|
53
|
+
*/
|
|
54
|
+
export declare const credentialAgentEndpoints: (processEnv: NodeJS.ProcessEnv, platform: NodeJS.Platform, privateTmpEntries?: () => readonly string[]) => string[];
|
|
55
|
+
/**
|
|
56
|
+
* Package-manager caches a build writes outside the workspace. Writable so
|
|
57
|
+
* `npm install` and friends work; nothing in them is a credential.
|
|
58
|
+
*/
|
|
59
|
+
export declare const DEFAULT_WRITABLE_HOME_PATHS: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* What stays readable when the home is hidden (the default): the tools a
|
|
62
|
+
* command runs and the config they read, read-only. The credential files
|
|
63
|
+
* inside them (`~/.cargo/credentials.toml`, `~/.gradle/gradle.properties`)
|
|
64
|
+
* stay denied; the writable caches are visible too. Everything else under
|
|
65
|
+
* the home (documents, other projects, browser and app data) is hidden.
|
|
66
|
+
*/
|
|
67
|
+
export declare const DEFAULT_VISIBLE_HOME_PATHS: readonly string[];
|
|
68
|
+
/**
|
|
69
|
+
* Whether a default writable path is one this platform uses. `Library` is
|
|
70
|
+
* macOS's; elsewhere it would only be a folder created for nothing.
|
|
71
|
+
*/
|
|
72
|
+
export declare const writableHomePathsFor: (platform: NodeJS.Platform) => string[];
|
|
73
|
+
export interface SandboxPolicy {
|
|
74
|
+
/** The agent's workspace: readable and writable. */
|
|
75
|
+
workspace: string;
|
|
76
|
+
/** Where the command starts. Writable too, when it is outside the workspace. */
|
|
77
|
+
cwd?: string;
|
|
78
|
+
/** Directories refused to the command, reads and writes (the Stratus home among them). */
|
|
79
|
+
denied: string[];
|
|
80
|
+
/** Directories the command may write besides the workspace and temp. */
|
|
81
|
+
writable: string[];
|
|
82
|
+
/** The daemon user's own temp directory (macOS keeps one per user under /var/folders). */
|
|
83
|
+
tmp?: string;
|
|
84
|
+
/**
|
|
85
|
+
* The user's home, hidden except `visible` (read-only unless also in
|
|
86
|
+
* `writable`). Absent: the home stays readable apart from `denied`.
|
|
87
|
+
*/
|
|
88
|
+
home?: {
|
|
89
|
+
path: string;
|
|
90
|
+
visible: string[];
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export interface SandboxedCommand {
|
|
94
|
+
command: string;
|
|
95
|
+
args: string[];
|
|
96
|
+
}
|
|
97
|
+
export type SandboxPlan = {
|
|
98
|
+
kind: 'sandboxed';
|
|
99
|
+
command: SandboxedCommand;
|
|
100
|
+
} | {
|
|
101
|
+
kind: 'unavailable';
|
|
102
|
+
reason: string;
|
|
103
|
+
};
|
|
104
|
+
/** Both spellings of a path: as given, and resolved through its symlinks when it exists. */
|
|
105
|
+
export declare const spellings: (target: string) => string[];
|
|
106
|
+
/**
|
|
107
|
+
* The Stratus homes an agent's command must not read: the configured one,
|
|
108
|
+
* and the one its workspace sits in when it uses the default layout
|
|
109
|
+
* (`<home>/agents/<id>/workspace`).
|
|
110
|
+
*/
|
|
111
|
+
export declare const stratusHomesFor: (workspace: string, processEnv: NodeJS.ProcessEnv, userHome: string) => string[];
|
|
112
|
+
/**
|
|
113
|
+
* The macOS profile. Rules are evaluated in order and the last match wins,
|
|
114
|
+
* so it allows everything, takes writes away, gives back the workspace and
|
|
115
|
+
* temp, takes the denied trees away entirely, and gives the workspace back
|
|
116
|
+
* once more (it may sit inside the Stratus home). The denied trees lose
|
|
117
|
+
* their contents, not their names: `stat` still works, so git and getcwd
|
|
118
|
+
* can walk up through them. Keychain lookups go
|
|
119
|
+
* through securityd rather than the filesystem, so its mach services are
|
|
120
|
+
* refused as well; TLS trust uses trustd and keeps working.
|
|
121
|
+
*/
|
|
122
|
+
export declare const darwinProfile: (policy: SandboxPolicy) => string;
|
|
123
|
+
export declare const bwrapArgs: (policy: SandboxPolicy, shell: string, shellArgs: string[]) => string[];
|
|
124
|
+
/** For tests: forget the cached bwrap probe. */
|
|
125
|
+
export declare const resetSandboxProbe: () => void;
|
|
126
|
+
/** How to run `shell shellArgs…` under the policy on this platform, or why it can't be. */
|
|
127
|
+
export declare const planSandbox: (policy: SandboxPolicy, shell: string, shellArgs: string[], platform?: NodeJS.Platform) => SandboxPlan;
|
|
128
|
+
export type HomeMode = 'hidden' | 'visible';
|
|
129
|
+
export declare const parseHomeMode: (value: unknown) => HomeMode;
|
|
130
|
+
export declare const parseSandboxMode: (value: unknown) => SandboxMode;
|
|
131
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
|
package/dist/sandbox.js
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readdirSync, realpathSync, statSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
/** Paths under the user's home that hold credentials, refused to every sandboxed command. */
|
|
5
|
+
export const DEFAULT_DENIED_HOME_PATHS = [
|
|
6
|
+
'.ssh',
|
|
7
|
+
'.aws',
|
|
8
|
+
'.azure',
|
|
9
|
+
'.config/gcloud',
|
|
10
|
+
'.config/gh',
|
|
11
|
+
'.config/git/credentials',
|
|
12
|
+
'.config/op',
|
|
13
|
+
'.docker',
|
|
14
|
+
'.fly',
|
|
15
|
+
'.git-credentials',
|
|
16
|
+
'.gnupg',
|
|
17
|
+
'.kube',
|
|
18
|
+
'.netrc',
|
|
19
|
+
'.npmrc',
|
|
20
|
+
'.password-store',
|
|
21
|
+
'.pypirc',
|
|
22
|
+
'Library/Keychains',
|
|
23
|
+
// Tokens developer CLIs store after a login.
|
|
24
|
+
'.cargo/credentials.toml',
|
|
25
|
+
'.cargo/credentials',
|
|
26
|
+
'.gem/credentials',
|
|
27
|
+
'.config/hub',
|
|
28
|
+
'.config/glab-cli',
|
|
29
|
+
'.terraform.d/credentials.tfrc.json',
|
|
30
|
+
'.vault-token',
|
|
31
|
+
'.pulumi/credentials.json',
|
|
32
|
+
'.m2/settings.xml',
|
|
33
|
+
'.m2/settings-security.xml',
|
|
34
|
+
'.gradle/gradle.properties',
|
|
35
|
+
'.composer/auth.json',
|
|
36
|
+
'.config/composer/auth.json',
|
|
37
|
+
'.databrickscfg',
|
|
38
|
+
'.config/doctl',
|
|
39
|
+
'.oci',
|
|
40
|
+
'.config/hcloud',
|
|
41
|
+
'.claude/.credentials.json',
|
|
42
|
+
'.codex/auth.json',
|
|
43
|
+
// SSH agents that keep their socket under the home: 1Password (Linux and
|
|
44
|
+
// macOS) and Secretive. An agent signs with keys no file check sees.
|
|
45
|
+
'.1password',
|
|
46
|
+
'Library/Group Containers/2BUA8C4S2C.com.1password',
|
|
47
|
+
'Library/Containers/com.maxgoedjen.Secretive.SecretAgent',
|
|
48
|
+
// Tokens kept inside a cache directory that is otherwise writable.
|
|
49
|
+
'.cache/huggingface/token',
|
|
50
|
+
'.cache/huggingface/stored_tokens',
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Control sockets of container runtimes. A read-only view of a socket still
|
|
54
|
+
* accepts a connection, and any of these hands out the whole host (`docker
|
|
55
|
+
* run -v /:/host`), so they are refused like the credential stores. Docker
|
|
56
|
+
* Desktop's own socket lives under `~/.docker`, which is denied already.
|
|
57
|
+
*/
|
|
58
|
+
export const DEFAULT_DENIED_SOCKETS = [
|
|
59
|
+
'/var/run/docker.sock',
|
|
60
|
+
'/run/docker.sock',
|
|
61
|
+
'/run/containerd/containerd.sock',
|
|
62
|
+
'/run/podman/podman.sock',
|
|
63
|
+
'/var/run/crio/crio.sock',
|
|
64
|
+
'/run/buildkit/buildkitd.sock',
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* The user's runtime directories, `$XDG_RUNTIME_DIR` and `/run/user/<uid>`,
|
|
68
|
+
* denied whole. Everything there is a per-user service endpoint: D-Bus and
|
|
69
|
+
* the systemd manager (either starts a same-user process outside the
|
|
70
|
+
* sandbox), rootless Docker and Podman, gpg-agent and systemd's ssh-agent
|
|
71
|
+
* (either signs with keys whose files are hidden). Naming entries one by
|
|
72
|
+
* one kept missing the next one. An abstract-namespace socket has no path
|
|
73
|
+
* to cover; the network is not unshared, so one listening there stays
|
|
74
|
+
* reachable.
|
|
75
|
+
*/
|
|
76
|
+
export const userRuntimeEndpoints = (processEnv, uid) => {
|
|
77
|
+
const dirs = new Set();
|
|
78
|
+
if (processEnv.XDG_RUNTIME_DIR && path.isAbsolute(processEnv.XDG_RUNTIME_DIR)) {
|
|
79
|
+
dirs.add(processEnv.XDG_RUNTIME_DIR);
|
|
80
|
+
}
|
|
81
|
+
if (uid !== undefined) {
|
|
82
|
+
dirs.add(`/run/user/${uid}`);
|
|
83
|
+
}
|
|
84
|
+
return [...dirs];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Variables that move a credential store out of its default place, and what
|
|
88
|
+
* under the moved location is the credential ('' for the location itself).
|
|
89
|
+
* The daemon's environment decides where the CLIs it runs keep tokens, so
|
|
90
|
+
* the moved store is denied even when the variable is not forwarded to the
|
|
91
|
+
* command: the command reads the file, not the variable.
|
|
92
|
+
*/
|
|
93
|
+
const RELOCATED_CREDENTIAL_STORES = [
|
|
94
|
+
['GH_CONFIG_DIR', ['']],
|
|
95
|
+
['DOCKER_CONFIG', ['']],
|
|
96
|
+
['AWS_SHARED_CREDENTIALS_FILE', ['']],
|
|
97
|
+
['AWS_CONFIG_FILE', ['']],
|
|
98
|
+
['GNUPGHOME', ['']],
|
|
99
|
+
['CLOUDSDK_CONFIG', ['']],
|
|
100
|
+
['AZURE_CONFIG_DIR', ['']],
|
|
101
|
+
['NPM_CONFIG_USERCONFIG', ['']],
|
|
102
|
+
['npm_config_userconfig', ['']],
|
|
103
|
+
['PASSWORD_STORE_DIR', ['']],
|
|
104
|
+
['CARGO_HOME', ['credentials.toml', 'credentials']],
|
|
105
|
+
['PULUMI_HOME', ['credentials.json']],
|
|
106
|
+
['TF_CLI_CONFIG_FILE', ['']],
|
|
107
|
+
['GRADLE_USER_HOME', ['gradle.properties']],
|
|
108
|
+
['COMPOSER_HOME', ['auth.json']],
|
|
109
|
+
['DATABRICKS_CONFIG_FILE', ['']],
|
|
110
|
+
['CLAUDE_CONFIG_DIR', ['.credentials.json']],
|
|
111
|
+
['CODEX_HOME', ['auth.json']],
|
|
112
|
+
['HF_HOME', ['token', 'stored_tokens']],
|
|
113
|
+
['HF_TOKEN_PATH', ['']],
|
|
114
|
+
['GLAB_CONFIG_DIR', ['']],
|
|
115
|
+
['HUB_CONFIG', ['']],
|
|
116
|
+
['OP_CONFIG_DIR', ['']],
|
|
117
|
+
// The daemon's own control-API token, when a mounted secret supplies it.
|
|
118
|
+
['STRATUS_GATEWAY_TOKEN_FILE', ['']],
|
|
119
|
+
];
|
|
120
|
+
/** XDG base directories, and the prefix of the default home entries each one moves. */
|
|
121
|
+
const XDG_BASES = [
|
|
122
|
+
['XDG_CONFIG_HOME', '.config/'],
|
|
123
|
+
['XDG_CACHE_HOME', '.cache/'],
|
|
124
|
+
];
|
|
125
|
+
/** Container runtime endpoints a variable names (`unix:///path`), like the default sockets. */
|
|
126
|
+
const SOCKET_HOSTS = ['DOCKER_HOST', 'CONTAINER_HOST'];
|
|
127
|
+
/**
|
|
128
|
+
* The credential stores, and container sockets, that the daemon's
|
|
129
|
+
* environment moves elsewhere. A relative value is ignored (it names no
|
|
130
|
+
* fixed place), and so is one that is or holds the user's home or the
|
|
131
|
+
* workspace: denying it would hide the whole system or the agent's own work,
|
|
132
|
+
* and the home's own credential paths are denied by name already.
|
|
133
|
+
*/
|
|
134
|
+
export const relocatedCredentials = (processEnv, userHome, workspace) => {
|
|
135
|
+
const found = [];
|
|
136
|
+
const add = (target) => {
|
|
137
|
+
if (!path.isAbsolute(target)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const resolved = path.resolve(target);
|
|
141
|
+
if (isWithin(resolved, path.resolve(userHome)) || isWithin(resolved, path.resolve(workspace))) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
found.push(resolved);
|
|
145
|
+
};
|
|
146
|
+
for (const [name, entries] of RELOCATED_CREDENTIAL_STORES) {
|
|
147
|
+
const value = processEnv[name];
|
|
148
|
+
if (value && path.isAbsolute(value)) {
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
add(path.join(value, entry));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (const [name, prefix] of XDG_BASES) {
|
|
155
|
+
const value = processEnv[name];
|
|
156
|
+
if (value && path.isAbsolute(value)) {
|
|
157
|
+
for (const entry of DEFAULT_DENIED_HOME_PATHS) {
|
|
158
|
+
if (entry.startsWith(prefix)) {
|
|
159
|
+
add(path.join(value, entry.slice(prefix.length)));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const entry of (processEnv.KUBECONFIG ?? '').split(path.delimiter)) {
|
|
165
|
+
add(entry);
|
|
166
|
+
}
|
|
167
|
+
for (const name of SOCKET_HOSTS) {
|
|
168
|
+
const value = processEnv[name];
|
|
169
|
+
if (value?.startsWith('unix://')) {
|
|
170
|
+
add(value.slice('unix://'.length));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return found;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* SSH agent sockets outside the home and runtime directory: the one
|
|
177
|
+
* `$SSH_AUTH_SOCK` names, and on macOS every launchd session directory in
|
|
178
|
+
* `/private/tmp` (launchd's own agent listens in one, under a random name a
|
|
179
|
+
* command can list). `/private/tmp` is otherwise writable to the command;
|
|
180
|
+
* Linux gives it a private `/tmp` already.
|
|
181
|
+
*/
|
|
182
|
+
export const credentialAgentEndpoints = (processEnv, platform, privateTmpEntries = () => {
|
|
183
|
+
try {
|
|
184
|
+
return readdirSync('/private/tmp');
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
}) => {
|
|
190
|
+
const found = [];
|
|
191
|
+
if (processEnv.SSH_AUTH_SOCK && path.isAbsolute(processEnv.SSH_AUTH_SOCK)) {
|
|
192
|
+
found.push(processEnv.SSH_AUTH_SOCK);
|
|
193
|
+
}
|
|
194
|
+
if (platform === 'darwin') {
|
|
195
|
+
for (const entry of privateTmpEntries()) {
|
|
196
|
+
if (entry.startsWith('com.apple.launchd.')) {
|
|
197
|
+
found.push(path.join('/private/tmp', entry));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return found;
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Package-manager caches a build writes outside the workspace. Writable so
|
|
205
|
+
* `npm install` and friends work; nothing in them is a credential.
|
|
206
|
+
*/
|
|
207
|
+
export const DEFAULT_WRITABLE_HOME_PATHS = [
|
|
208
|
+
'.npm',
|
|
209
|
+
'.cache',
|
|
210
|
+
'.pnpm-store',
|
|
211
|
+
'.bun/install/cache',
|
|
212
|
+
'.yarn/berry/cache',
|
|
213
|
+
'Library/Caches',
|
|
214
|
+
'Library/pnpm',
|
|
215
|
+
];
|
|
216
|
+
/**
|
|
217
|
+
* What stays readable when the home is hidden (the default): the tools a
|
|
218
|
+
* command runs and the config they read, read-only. The credential files
|
|
219
|
+
* inside them (`~/.cargo/credentials.toml`, `~/.gradle/gradle.properties`)
|
|
220
|
+
* stay denied; the writable caches are visible too. Everything else under
|
|
221
|
+
* the home (documents, other projects, browser and app data) is hidden.
|
|
222
|
+
*/
|
|
223
|
+
export const DEFAULT_VISIBLE_HOME_PATHS = [
|
|
224
|
+
// Git and shell config a command reads.
|
|
225
|
+
'.gitconfig',
|
|
226
|
+
'.gitignore_global',
|
|
227
|
+
'.config/git',
|
|
228
|
+
'.editorconfig',
|
|
229
|
+
// Language toolchains and version managers.
|
|
230
|
+
'.nvm',
|
|
231
|
+
'.volta',
|
|
232
|
+
'.fnm',
|
|
233
|
+
'.bun',
|
|
234
|
+
'.deno',
|
|
235
|
+
'.rustup',
|
|
236
|
+
'.cargo',
|
|
237
|
+
'.pyenv',
|
|
238
|
+
'.rbenv',
|
|
239
|
+
'.rye',
|
|
240
|
+
'.asdf',
|
|
241
|
+
'.tool-versions',
|
|
242
|
+
'.sdkman',
|
|
243
|
+
'.gradle',
|
|
244
|
+
'.m2',
|
|
245
|
+
'.gem',
|
|
246
|
+
'go',
|
|
247
|
+
'.nix-profile',
|
|
248
|
+
'.local/bin',
|
|
249
|
+
'.local/lib',
|
|
250
|
+
'.local/share/mise',
|
|
251
|
+
'.local/share/fnm',
|
|
252
|
+
'.local/share/pnpm',
|
|
253
|
+
'.local/share/uv',
|
|
254
|
+
'.config/mise',
|
|
255
|
+
'.config/uv',
|
|
256
|
+
];
|
|
257
|
+
/**
|
|
258
|
+
* Whether a default writable path is one this platform uses. `Library` is
|
|
259
|
+
* macOS's; elsewhere it would only be a folder created for nothing.
|
|
260
|
+
*/
|
|
261
|
+
export const writableHomePathsFor = (platform) => DEFAULT_WRITABLE_HOME_PATHS.filter((entry) => platform === 'darwin' || !entry.startsWith('Library/'));
|
|
262
|
+
/** Both spellings of a path: as given, and resolved through its symlinks when it exists. */
|
|
263
|
+
export const spellings = (target) => {
|
|
264
|
+
const absolute = path.resolve(target);
|
|
265
|
+
try {
|
|
266
|
+
const real = realpathSync(absolute);
|
|
267
|
+
return real === absolute ? [absolute] : [absolute, real];
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return [absolute];
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* The Stratus homes an agent's command must not read: the configured one,
|
|
275
|
+
* and the one its workspace sits in when it uses the default layout
|
|
276
|
+
* (`<home>/agents/<id>/workspace`).
|
|
277
|
+
*/
|
|
278
|
+
export const stratusHomesFor = (workspace, processEnv, userHome) => {
|
|
279
|
+
const homes = new Set();
|
|
280
|
+
homes.add(path.resolve(processEnv.STRATUS_HOME ?? path.join(userHome, '.stratus')));
|
|
281
|
+
const parts = path.resolve(workspace).split(path.sep);
|
|
282
|
+
if (parts.length >= 4 && parts.at(-1) === 'workspace' && parts.at(-3) === 'agents') {
|
|
283
|
+
homes.add(parts.slice(0, -3).join(path.sep) || path.sep);
|
|
284
|
+
}
|
|
285
|
+
return [...homes];
|
|
286
|
+
};
|
|
287
|
+
/** Whether `child` is `parent` or beneath it. */
|
|
288
|
+
const isWithin = (parent, child) => {
|
|
289
|
+
const relative = path.relative(parent, child);
|
|
290
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* The denied paths that sit inside the workspace, every spelling. The
|
|
294
|
+
* workspace is given back after the denials (it may sit inside the hidden
|
|
295
|
+
* Stratus home), so these are denied once more after it: a workspace that
|
|
296
|
+
* is an ancestor of something hidden (a fallback of `~` or `/`, or an
|
|
297
|
+
* operator's `deniedPaths` entry inside it) must not show it again.
|
|
298
|
+
*/
|
|
299
|
+
const deniedInside = (policy) => {
|
|
300
|
+
const workspace = spellings(policy.workspace);
|
|
301
|
+
return [...new Set(policy.denied.flatMap(spellings))].filter((denied) => workspace.some((dir) => isWithin(dir, denied)));
|
|
302
|
+
};
|
|
303
|
+
const SBPL_UNSAFE = /["\\\n\r\0]/;
|
|
304
|
+
const sbplString = (value) => {
|
|
305
|
+
if (SBPL_UNSAFE.test(value)) {
|
|
306
|
+
throw new Error(`Cannot sandbox a path containing a quote, backslash, or newline: ${JSON.stringify(value)}`);
|
|
307
|
+
}
|
|
308
|
+
return `"${value}"`;
|
|
309
|
+
};
|
|
310
|
+
const subpaths = (paths) => [...new Set(paths.flatMap(spellings))].map((p) => `(subpath ${sbplString(p)})`).join(' ');
|
|
311
|
+
/** Deny reading, writing, and connecting to sockets under `paths`. */
|
|
312
|
+
const denyRules = (paths) => paths.length === 0 ? [] : [
|
|
313
|
+
`(deny file-read-data file-read-xattr file-write* ${subpaths(paths)})`,
|
|
314
|
+
// A file deny does not cover connect(2) on a socket inside it. One
|
|
315
|
+
// `remote unix-socket` form per path: given several paths, one form
|
|
316
|
+
// matches only its first (measured on macOS 15.3).
|
|
317
|
+
`(deny network-outbound ${[...new Set(paths.flatMap(spellings))].map((p) => `(remote unix-socket (subpath ${sbplString(p)}))`).join(' ')})`,
|
|
318
|
+
];
|
|
319
|
+
/**
|
|
320
|
+
* Hide the home: its contents and any socket under it, then give the
|
|
321
|
+
* visible entries, the writable caches, and a configured cwd back for
|
|
322
|
+
* reading. Comes before the denials, so a
|
|
323
|
+
* credential inside a visible toolchain stays hidden.
|
|
324
|
+
*/
|
|
325
|
+
const hideHomeRules = (policy) => {
|
|
326
|
+
if (!policy.home) {
|
|
327
|
+
return [];
|
|
328
|
+
}
|
|
329
|
+
// A configured cwd is where commands start, so it is read like the
|
|
330
|
+
// workspace (Codex P1 4316843343); credentials inside it stay denied below.
|
|
331
|
+
const visible = [...new Set([...policy.home.visible, ...policy.writable, ...(policy.cwd ? [policy.cwd] : [])])];
|
|
332
|
+
return [
|
|
333
|
+
`(deny file-read-data file-read-xattr ${subpaths([policy.home.path])})`,
|
|
334
|
+
...[...new Set(spellings(policy.home.path))].map((p) => `(deny network-outbound (remote unix-socket (subpath ${sbplString(p)})))`),
|
|
335
|
+
...(visible.length > 0 ? [`(allow file-read-data file-read-xattr ${subpaths(visible)})`] : []),
|
|
336
|
+
];
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* The macOS profile. Rules are evaluated in order and the last match wins,
|
|
340
|
+
* so it allows everything, takes writes away, gives back the workspace and
|
|
341
|
+
* temp, takes the denied trees away entirely, and gives the workspace back
|
|
342
|
+
* once more (it may sit inside the Stratus home). The denied trees lose
|
|
343
|
+
* their contents, not their names: `stat` still works, so git and getcwd
|
|
344
|
+
* can walk up through them. Keychain lookups go
|
|
345
|
+
* through securityd rather than the filesystem, so its mach services are
|
|
346
|
+
* refused as well; TLS trust uses trustd and keeps working.
|
|
347
|
+
*/
|
|
348
|
+
export const darwinProfile = (policy) => {
|
|
349
|
+
const writable = [policy.workspace, ...(policy.cwd ? [policy.cwd] : []), ...policy.writable, '/private/tmp', ...(policy.tmp ? [policy.tmp] : [])];
|
|
350
|
+
const ancestors = [...new Set([policy.workspace, ...(policy.cwd ? [policy.cwd] : [])].flatMap(spellings).flatMap((dir) => {
|
|
351
|
+
const chain = [];
|
|
352
|
+
for (let current = path.dirname(dir);; current = path.dirname(current)) {
|
|
353
|
+
chain.push(current);
|
|
354
|
+
if (path.dirname(current) === current) {
|
|
355
|
+
return chain;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}))];
|
|
359
|
+
return [
|
|
360
|
+
'(version 1)',
|
|
361
|
+
'(allow default)',
|
|
362
|
+
'(deny file-write* (subpath "/"))',
|
|
363
|
+
`(allow file-write* ${subpaths(writable)} (literal "/dev/null") (literal "/dev/zero") (literal "/dev/dtracehelper") (regex #"^/dev/tty") (regex #"^/dev/fd/"))`,
|
|
364
|
+
...hideHomeRules(policy),
|
|
365
|
+
...denyRules(policy.denied),
|
|
366
|
+
'(deny mach-lookup (global-name "com.apple.SecurityServer") (global-name "com.apple.securityd.xpc"))',
|
|
367
|
+
// The workspace's ancestors may be listed (not read into), or getcwd
|
|
368
|
+
// and git's repository discovery fail when the workspace sits inside
|
|
369
|
+
// the hidden Stratus home. A listing names files; it reads none.
|
|
370
|
+
...(ancestors.length > 0 ? [`(allow file-read-data ${ancestors.map((p) => `(literal ${sbplString(p)})`).join(' ')})`] : []),
|
|
371
|
+
// Named operation by operation: an allow of the `file-read*` wildcard
|
|
372
|
+
// does not undo a deny that named `file-read-data`.
|
|
373
|
+
`(allow file-read-data file-read-xattr file-read* file-write* ${subpaths([policy.workspace])})`,
|
|
374
|
+
...denyRules(deniedInside(policy)),
|
|
375
|
+
'',
|
|
376
|
+
].join('\n');
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* The bubblewrap arguments. The root is bound read-only, temp is private,
|
|
380
|
+
* each denied path that exists is covered (an empty tmpfs over a directory,
|
|
381
|
+
* `/dev/null` over a file), and the workspace is bound back last so it
|
|
382
|
+
* shows through a covered Stratus home. A fresh pid and IPC namespace keep
|
|
383
|
+
* the command from signalling the daemon or other agents.
|
|
384
|
+
*/
|
|
385
|
+
/**
|
|
386
|
+
* The daemon's temp directory when it is not under `/tmp`, which gets a
|
|
387
|
+
* private tmpfs of its own the way `/tmp` does, so tools that honor
|
|
388
|
+
* `TMPDIR` can write there. Not one that holds the workspace or the
|
|
389
|
+
* starting directory (`TMPDIR=$HOME`): an empty tmpfs there would hide the
|
|
390
|
+
* toolchains a command needs.
|
|
391
|
+
*/
|
|
392
|
+
const privateTmpFor = (policy) => {
|
|
393
|
+
if (!policy.tmp) {
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
const tmp = path.resolve(policy.tmp);
|
|
397
|
+
if (tmp === '/' || isWithin('/tmp', tmp) || !existsSync(tmp) || !statSync(tmp).isDirectory()) {
|
|
398
|
+
return undefined;
|
|
399
|
+
}
|
|
400
|
+
const held = [policy.workspace, ...(policy.cwd ? [policy.cwd] : [])].flatMap(spellings);
|
|
401
|
+
return held.some((dir) => isWithin(tmp, dir)) ? undefined : tmp;
|
|
402
|
+
};
|
|
403
|
+
/**
|
|
404
|
+
* An existing path as bwrap must mount it: at its real path, and nowhere
|
|
405
|
+
* else. bwrap resolves an absolute symlink against the host root while it
|
|
406
|
+
* builds the new one, so a mount through a linked directory (`/var/run` is
|
|
407
|
+
* `/run` on most distributions) fails before the command starts. The alias
|
|
408
|
+
* resolves to the real path inside the sandbox, so one mount covers both
|
|
409
|
+
* names. A path that does not exist has nothing to cover.
|
|
410
|
+
*/
|
|
411
|
+
const realOnly = (target) => {
|
|
412
|
+
try {
|
|
413
|
+
return [realpathSync(target)];
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
return [];
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
export const bwrapArgs = (policy, shell, shellArgs) => {
|
|
420
|
+
const args = ['--ro-bind', '/', '/', '--dev', '/dev', '--proc', '/proc', '--tmpfs', '/tmp'];
|
|
421
|
+
// The hidden home first: an empty tmpfs over it, the visible entries
|
|
422
|
+
// bound back read-only. Everything after binds over this.
|
|
423
|
+
// Everything at real paths only (see realOnly): an entry is given back
|
|
424
|
+
// where its name lands under the real home and, when it links elsewhere in
|
|
425
|
+
// the home, at its target too, since the tmpfs hid both.
|
|
426
|
+
const home = policy.home ? realOnly(policy.home.path)[0] : undefined;
|
|
427
|
+
if (policy.home && home) {
|
|
428
|
+
args.push('--tmpfs', home);
|
|
429
|
+
for (const entry of new Set(policy.home.visible)) {
|
|
430
|
+
const source = realOnly(entry)[0];
|
|
431
|
+
if (!source) {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const named = path.resolve(entry);
|
|
435
|
+
const dest = isWithin(policy.home.path, named) ? path.join(home, path.relative(policy.home.path, named)) : source;
|
|
436
|
+
for (const target of new Set([dest, ...(isWithin(home, source) ? [source] : [])])) {
|
|
437
|
+
args.push('--ro-bind', source, target);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const tmp = privateTmpFor(policy);
|
|
442
|
+
if (tmp) {
|
|
443
|
+
args.push('--tmpfs', tmp);
|
|
444
|
+
}
|
|
445
|
+
for (const dir of new Set([...policy.writable, ...(policy.cwd ? [policy.cwd] : [])].flatMap(realOnly))) {
|
|
446
|
+
args.push('--bind', dir, dir);
|
|
447
|
+
}
|
|
448
|
+
for (const denied of new Set(policy.denied.flatMap(realOnly))) {
|
|
449
|
+
if (statSync(denied).isDirectory()) {
|
|
450
|
+
args.push('--tmpfs', denied);
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
args.push('--ro-bind', '/dev/null', denied);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
const workspaceSpellings = spellings(policy.workspace);
|
|
457
|
+
const workspaceSource = workspaceSpellings.at(-1);
|
|
458
|
+
for (const spelling of workspaceSpellings) {
|
|
459
|
+
args.push('--bind', workspaceSource, spelling);
|
|
460
|
+
}
|
|
461
|
+
for (const denied of new Set(deniedInside(policy).flatMap(realOnly))) {
|
|
462
|
+
args.push(statSync(denied).isDirectory() ? '--tmpfs' : '--ro-bind', ...(statSync(denied).isDirectory() ? [denied] : ['/dev/null', denied]));
|
|
463
|
+
}
|
|
464
|
+
args.push('--unshare-pid', '--unshare-ipc', '--die-with-parent', '--new-session');
|
|
465
|
+
if (policy.cwd) {
|
|
466
|
+
args.push('--chdir', policy.cwd);
|
|
467
|
+
}
|
|
468
|
+
args.push('--', shell, ...shellArgs);
|
|
469
|
+
return args;
|
|
470
|
+
};
|
|
471
|
+
const DARWIN_SANDBOX_EXEC = '/usr/bin/sandbox-exec';
|
|
472
|
+
const BWRAP_CANDIDATES = ['/usr/bin/bwrap', '/usr/local/bin/bwrap', '/bin/bwrap'];
|
|
473
|
+
let bwrapProbe;
|
|
474
|
+
/** Whether bwrap can actually start a namespace here (it can't in many containers). Probed once. */
|
|
475
|
+
const probeBwrap = () => {
|
|
476
|
+
if (bwrapProbe) {
|
|
477
|
+
return bwrapProbe;
|
|
478
|
+
}
|
|
479
|
+
const found = BWRAP_CANDIDATES.find((candidate) => existsSync(candidate));
|
|
480
|
+
if (!found) {
|
|
481
|
+
bwrapProbe = { error: 'bubblewrap (bwrap) is not installed. Install it (apt install bubblewrap, dnf install bubblewrap)' };
|
|
482
|
+
return bwrapProbe;
|
|
483
|
+
}
|
|
484
|
+
const result = spawnSync(found, ['--ro-bind', '/', '/', '--unshare-pid', '--', '/bin/true'], { encoding: 'utf8', timeout: 5_000 });
|
|
485
|
+
bwrapProbe = result.status === 0
|
|
486
|
+
? { path: found }
|
|
487
|
+
: { error: `${found} cannot create a sandbox here (${(result.stderr || result.error?.message || `exit ${result.status}`).trim()})` };
|
|
488
|
+
return bwrapProbe;
|
|
489
|
+
};
|
|
490
|
+
/** For tests: forget the cached bwrap probe. */
|
|
491
|
+
export const resetSandboxProbe = () => {
|
|
492
|
+
bwrapProbe = undefined;
|
|
493
|
+
};
|
|
494
|
+
/** How to run `shell shellArgs…` under the policy on this platform, or why it can't be. */
|
|
495
|
+
export const planSandbox = (policy, shell, shellArgs, platform = process.platform) => {
|
|
496
|
+
if (platform === 'darwin') {
|
|
497
|
+
if (!existsSync(DARWIN_SANDBOX_EXEC)) {
|
|
498
|
+
return { kind: 'unavailable', reason: `${DARWIN_SANDBOX_EXEC} is missing` };
|
|
499
|
+
}
|
|
500
|
+
return { kind: 'sandboxed', command: { command: DARWIN_SANDBOX_EXEC, args: ['-p', darwinProfile(policy), shell, ...shellArgs] } };
|
|
501
|
+
}
|
|
502
|
+
if (platform === 'linux') {
|
|
503
|
+
const probe = probeBwrap();
|
|
504
|
+
if ('error' in probe) {
|
|
505
|
+
return { kind: 'unavailable', reason: probe.error };
|
|
506
|
+
}
|
|
507
|
+
return { kind: 'sandboxed', command: { command: probe.path, args: bwrapArgs(policy, shell, shellArgs) } };
|
|
508
|
+
}
|
|
509
|
+
return { kind: 'unavailable', reason: `no sandbox is implemented for ${platform}` };
|
|
510
|
+
};
|
|
511
|
+
export const parseHomeMode = (value) => {
|
|
512
|
+
if (value === undefined) {
|
|
513
|
+
return 'hidden';
|
|
514
|
+
}
|
|
515
|
+
if (value === 'hidden' || value === 'visible') {
|
|
516
|
+
return value;
|
|
517
|
+
}
|
|
518
|
+
throw new Error(`home must be "hidden" or "visible"; got ${JSON.stringify(value)}.`);
|
|
519
|
+
};
|
|
520
|
+
export const parseSandboxMode = (value) => {
|
|
521
|
+
// Required by default: commands run without asking under the open
|
|
522
|
+
// posture, so an unconfined shell is a refusal, not a warning.
|
|
523
|
+
if (value === undefined) {
|
|
524
|
+
return 'required';
|
|
525
|
+
}
|
|
526
|
+
if (value === 'auto' || value === 'required' || value === 'off') {
|
|
527
|
+
return value;
|
|
528
|
+
}
|
|
529
|
+
throw new Error(`sandbox must be "auto", "required", or "off"; got ${JSON.stringify(value)}.`);
|
|
530
|
+
};
|
|
531
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,IAAI,MAAM,WAAW,CAAC;AAsB7B,6FAA6F;AAC7F,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,MAAM;IACN,MAAM;IACN,QAAQ;IACR,gBAAgB;IAChB,YAAY;IACZ,yBAAyB;IACzB,YAAY;IACZ,SAAS;IACT,MAAM;IACN,kBAAkB;IAClB,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,iBAAiB;IACjB,SAAS;IACT,mBAAmB;IACnB,6CAA6C;IAC7C,yBAAyB;IACzB,oBAAoB;IACpB,kBAAkB;IAClB,aAAa;IACb,kBAAkB;IAClB,oCAAoC;IACpC,cAAc;IACd,0BAA0B;IAC1B,kBAAkB;IAClB,2BAA2B;IAC3B,2BAA2B;IAC3B,qBAAqB;IACrB,4BAA4B;IAC5B,gBAAgB;IAChB,eAAe;IACf,MAAM;IACN,gBAAgB;IAChB,2BAA2B;IAC3B,kBAAkB;IAClB,yEAAyE;IACzE,qEAAqE;IACrE,YAAY;IACZ,mDAAmD;IACnD,yDAAyD;IACzD,mEAAmE;IACnE,0BAA0B;IAC1B,kCAAkC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD,sBAAsB;IACtB,kBAAkB;IAClB,iCAAiC;IACjC,yBAAyB;IACzB,yBAAyB;IACzB,8BAA8B;CAC/B,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAA6B,EAAE,GAAuB,EAAY,EAAE;IACvG,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,UAAU,CAAC,eAAe,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9E,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,EAAE,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAwD;IACvF,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,6BAA6B,EAAE,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC,oBAAoB,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,YAAY,EAAE,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC,aAAa,EAAE,CAAC,kBAAkB,CAAC,CAAC;IACrC,CAAC,oBAAoB,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,kBAAkB,EAAE,CAAC,mBAAmB,CAAC,CAAC;IAC3C,CAAC,eAAe,EAAE,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC,wBAAwB,EAAE,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,mBAAmB,EAAE,CAAC,mBAAmB,CAAC,CAAC;IAC5C,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACvC,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,yEAAyE;IACzE,CAAC,4BAA4B,EAAE,CAAC,EAAE,CAAC,CAAC;CACrC,CAAC;AAEF,uFAAuF;AACvF,MAAM,SAAS,GAA6C;IAC1D,CAAC,iBAAiB,EAAE,UAAU,CAAC;IAC/B,CAAC,gBAAgB,EAAE,SAAS,CAAC;CAC9B,CAAC;AAEF,+FAA+F;AAC/F,MAAM,YAAY,GAAG,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAA6B,EAAE,QAAgB,EAAE,SAAiB,EAAY,EAAE;IACnH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,EAAE;QAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YAC9F,OAAO;QACT,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,2BAA2B,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,KAAK,MAAM,KAAK,IAAI,yBAAyB,EAAE,CAAC;gBAC9C,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC7B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,KAAK,CAAC,CAAC;IACb,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,UAA6B,EAC7B,QAAyB,EACzB,oBAA6C,GAAG,EAAE;IAChD,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,EACS,EAAE;IACZ,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,UAAU,CAAC,aAAa,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1E,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,EAAE,CAAC;YACxC,IAAI,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAsB;IAC5D,MAAM;IACN,QAAQ;IACR,aAAa;IACb,oBAAoB;IACpB,mBAAmB;IACnB,gBAAgB;IAChB,cAAc;CACf,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsB;IAC3D,wCAAwC;IACxC,YAAY;IACZ,mBAAmB;IACnB,aAAa;IACb,eAAe;IACf,4CAA4C;IAC5C,MAAM;IACN,QAAQ;IACR,MAAM;IACN,MAAM;IACN,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO;IACP,gBAAgB;IAChB,SAAS;IACT,SAAS;IACT,KAAK;IACL,MAAM;IACN,IAAI;IACJ,cAAc;IACd,YAAY;IACZ,YAAY;IACZ,mBAAmB;IACnB,kBAAkB;IAClB,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,YAAY;CACb,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAyB,EAAY,EAAE,CAC1E,2BAA2B,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;AA6BxG,4FAA4F;AAC5F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAY,EAAE;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpB,CAAC;AACH,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAE,UAA6B,EAAE,QAAgB,EAAY,EAAE;IAC9G,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnF,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC,CAAC;AAEF,iDAAiD;AACjD,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,KAAa,EAAW,EAAE;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,YAAY,GAAG,CAAC,MAAqB,EAAY,EAAE;IACvD,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3H,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE;IAC3C,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,oEAAoE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,IAAI,KAAK,GAAG,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,KAAe,EAAU,EAAE,CAC3C,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE5F,sEAAsE;AACtE,MAAM,SAAS,GAAG,CAAC,KAAe,EAAY,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzE,oDAAoD,QAAQ,CAAC,KAAK,CAAC,GAAG;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,mDAAmD;IACnD,0BAA0B,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gCAAgC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG;CAC5I,CAAC;AAEF;;;;;GAKG;AACH,MAAM,aAAa,GAAG,CAAC,MAAqB,EAAY,EAAE;IACxD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,mEAAmE;IACnE,4EAA4E;IAC5E,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChH,OAAO;QACL,wCAAwC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG;QACvE,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uDAAuD,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;QAClI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,yCAAyC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/F,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAqB,EAAU,EAAE;IAC7D,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClJ,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACvH,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACpB,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,EAAE,CAAC;oBACtC,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC,CAAC,CAAC;IACL,OAAO;QACL,aAAa;QACb,iBAAiB;QACjB,kCAAkC;QAClC,sBAAsB,QAAQ,CAAC,QAAQ,CAAC,uHAAuH;QAC/J,GAAG,aAAa,CAAC,MAAM,CAAC;QACxB,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;QAC3B,qGAAqG;QACrG,qEAAqE;QACrE,qEAAqE;QACrE,iEAAiE;QACjE,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3H,sEAAsE;QACtE,oDAAoD;QACpD,gEAAgE,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG;QAC/F,GAAG,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAClC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;GAMG;AACH;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,CAAC,MAAqB,EAAsB,EAAE;IAClE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAChB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC7F,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;AAClE,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAY,EAAE;IAC5C,IAAI,CAAC;QACH,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAqB,EAAE,KAAa,EAAE,SAAmB,EAAY,EAAE;IAC/F,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5F,qEAAqE;IACrE,0DAA0D;IAC1D,uEAAuE;IACvE,2EAA2E;IAC3E,yDAAyD;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,IAAI,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAClH,KAAK,MAAM,MAAM,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACvG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC9D,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,eAAe,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC;IACnD,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9I,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC;IAClF,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;AACpD,MAAM,gBAAgB,GAAG,CAAC,gBAAgB,EAAE,sBAAsB,EAAE,YAAY,CAAC,CAAC;AAElF,IAAI,UAA4D,CAAC;AAEjE,oGAAoG;AACpG,MAAM,UAAU,GAAG,GAAyC,EAAE;IAC5D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,UAAU,GAAG,EAAE,KAAK,EAAE,kGAAkG,EAAE,CAAC;QAC3H,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACnI,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;QAC9B,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE;QACjB,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,kCAAkC,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;IACvI,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF,gDAAgD;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAS,EAAE;IAC1C,UAAU,GAAG,SAAS,CAAC;AACzB,CAAC,CAAC;AAEF,2FAA2F;AAC3F,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,MAAqB,EACrB,KAAa,EACb,SAAmB,EACnB,WAA4B,OAAO,CAAC,QAAQ,EAC/B,EAAE;IACf,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,mBAAmB,aAAa,EAAE,CAAC;QAC9E,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,EAAE,EAAE,CAAC;IACpI,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YACrB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QACtD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;IAC5G,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,iCAAiC,QAAQ,EAAE,EAAE,CAAC;AACtF,CAAC,CAAC;AAIF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAAY,EAAE;IACxD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAe,EAAE;IAC9D,kEAAkE;IAClE,+DAA+D;IAC/D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qDAAqD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACjG,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratusagent/tool-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
"node": ">=22.13 <23 || >=23.4"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@stratusagent/core": "0.
|
|
22
|
-
"@stratusagent/executor-local": "0.
|
|
23
|
-
"@stratusagent/plugins": "0.
|
|
21
|
+
"@stratusagent/core": "0.13.0",
|
|
22
|
+
"@stratusagent/executor-local": "0.13.0",
|
|
23
|
+
"@stratusagent/plugins": "0.13.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^24.6.0",
|
|
27
27
|
"typescript": "^5.9.3",
|
|
28
|
-
"@stratusagent/permissions": "0.
|
|
28
|
+
"@stratusagent/permissions": "0.13.0"
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"repository": {
|
|
@@ -82,6 +82,39 @@
|
|
|
82
82
|
},
|
|
83
83
|
"workspaceRoot": {
|
|
84
84
|
"type": "string"
|
|
85
|
+
},
|
|
86
|
+
"sandbox": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"enum": [
|
|
89
|
+
"auto",
|
|
90
|
+
"required",
|
|
91
|
+
"off"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"deniedPaths": {
|
|
95
|
+
"type": "array",
|
|
96
|
+
"items": {
|
|
97
|
+
"type": "string"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"writablePaths": {
|
|
101
|
+
"type": "array",
|
|
102
|
+
"items": {
|
|
103
|
+
"type": "string"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"home": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"enum": [
|
|
109
|
+
"hidden",
|
|
110
|
+
"visible"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
"readablePaths": {
|
|
114
|
+
"type": "array",
|
|
115
|
+
"items": {
|
|
116
|
+
"type": "string"
|
|
117
|
+
}
|
|
85
118
|
}
|
|
86
119
|
},
|
|
87
120
|
"additionalProperties": false
|