@deepseek-ai/dsh-bash-sandbox 0.1.5-rc.1 → 0.1.6-alpha.1
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.i18n.yaml +2 -2
- package/README.md +4 -4
- package/README.zh.md +9 -9
- package/lib/index.js +32 -95
- package/lib/types/helpers.d.ts +2 -46
- package/lib/types/index.d.ts +2 -1
- package/package.json +12 -12
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/shell/bash-sandbox/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: d9dbc85252a202dc7800eb727abd7700f5989fae
|
|
6
|
+
README.zh.md: 23ca4b5c59da2998b2b0aa546954591bf62da546
|
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ This section explains the design of the executor and points at the code that rea
|
|
|
75
75
|
|
|
76
76
|
### Design concept
|
|
77
77
|
|
|
78
|
-
The executor is the sandboxing Service Provider for the `ctx.shell` seam: it inherits `dsh-bash-local`'s process mechanics and
|
|
78
|
+
The executor is the sandboxing Service Provider for the `ctx.shell` seam: it inherits `dsh-bash-local`'s process mechanics and awaits confinement of each command's exact `['bash', '-c', command]` argv through `ctx.sandbox.confine()`, spawning the returned argv directly. Foreground preparation uses the local executor’s shared command deadline; timeout before spawn carries no enforcement claim. Background preparation follows only the caller signal. Both paths recheck cancellation before spawn. Which platform runner confines the command — and whether one is usable at all — is the provider's concern; this package owns the bash side only: the selected mode, enforcement completeness, and denial classification on results.
|
|
79
79
|
|
|
80
80
|
### Source map
|
|
81
81
|
|
|
@@ -83,7 +83,7 @@ The executor is the sandboxing Service Provider for the `ctx.shell` seam: it inh
|
|
|
83
83
|
|---|---|
|
|
84
84
|
| [`src/index.ts`](src/index.ts) | Plugin entry: `SandboxBashExecutor`, per-process fact retention, run/start wrapping |
|
|
85
85
|
| [`src/helpers.ts`](src/helpers.ts) | Denial, runner-failure, and runner-spawn-failure classification |
|
|
86
|
-
| — | No runtime invariant companion is published; this package exposes no independent event sequence or mutable data relation beyond contracts enforced at its owning seam. |
|
|
86
|
+
| — | No runtime invariant companion is published; classification is observable in results, and this package exposes no independent event sequence or mutable data relation beyond contracts enforced at its owning seam. |
|
|
87
87
|
| `tests/` | Exercised behavior across the bwrap, Landlock, and Seatbelt runners |
|
|
88
88
|
|
|
89
89
|
### Main flow
|
|
@@ -92,7 +92,7 @@ For a confined mode, `resolve()` stamps the per-call policy (the session's mode
|
|
|
92
92
|
|
|
93
93
|
### Invariants
|
|
94
94
|
|
|
95
|
-
- **Fail closed** — a confined mode with no usable runner
|
|
95
|
+
- **Fail closed** — a confined mode with no usable runner rejects with `SANDBOX_UNAVAILABLE`; unconfined passthrough never happens for a confined policy.
|
|
96
96
|
- **Deny-only at the seam** — this executor never grants permission; the approval flow lives in the tool layer.
|
|
97
97
|
- **Per-process facts** — confinement facts are retained per handle until settlement, because a provider may vary enforcement between overlapping calls.
|
|
98
98
|
- **File effects only** — the mode vocabulary claims only file effects.
|
|
@@ -170,7 +170,7 @@ These limits define when this executor is not a general security boundary. They
|
|
|
170
170
|
|
|
171
171
|
- **Confinement covers file effects only** — network restriction and a uniform process-visibility guarantee are absent, so the modes are not a general-purpose security sandbox.
|
|
172
172
|
- **Denials are inferred from failed-command stderr** — backend signatures make the inference portable, but a matching application error can be classified as a denial and a denial omitted from the retained tail can be missed.
|
|
173
|
-
- **An asynchronously observed background runner failure has no immediate error channel** — it is recorded on the settled process and surfaces when the caller reads the generic task with `job_output`; a synchronous subprocess throw that names the runner path
|
|
173
|
+
- **An asynchronously observed background runner failure has no immediate error channel** — it is recorded on the settled process and surfaces when the caller reads the generic task with `job_output`; a synchronous subprocess throw that names the runner path rejects `start()` before a handle is published.
|
|
174
174
|
- **`danger-full-access` deliberately bypasses `ctx.sandbox`** — it is an explicit unconfined mode, not a wider sandbox profile.
|
|
175
175
|
|
|
176
176
|
<a id="dev-note"></a>
|
package/README.zh.md
CHANGED
|
@@ -25,7 +25,7 @@ kind: "package-reference"
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## 使用本包
|
|
27
27
|
|
|
28
|
-
当命令不得以 harness 进程的完整文件权限运行时,用本执行器替代 `dsh-bash-local`。它注册为 `ctx.shell`,并要求一个 `ctx.sandbox` 提供方加上 `ctx.sandboxPolicy`;面向模型的 `bash` 工具基于它不加改动地工作,并公布 `sandbox_permissions
|
|
28
|
+
当命令不得以 harness 进程的完整文件权限运行时,用本执行器替代 `dsh-bash-local`。它注册为 `ctx.shell`,并要求一个 `ctx.sandbox` 提供方加上 `ctx.sandboxPolicy`;面向模型的 `bash` 工具基于它不加改动地工作,并公布 `sandbox_permissions` 与 `justification` 升权字段。
|
|
29
29
|
|
|
30
30
|
### 何时选择
|
|
31
31
|
|
|
@@ -71,11 +71,11 @@ kind: "package-reference"
|
|
|
71
71
|
<details>
|
|
72
72
|
<summary>实现细节——点击展开</summary>
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
本节解释执行器的设计并指出实现该设计的代码位置;可观察行为已在[使用本包](#use-this-package)中完整说明。
|
|
75
75
|
|
|
76
76
|
### 设计概念
|
|
77
77
|
|
|
78
|
-
本执行器是 `ctx.shell` seam 的沙箱 Service Provider:它继承 `dsh-bash-local`
|
|
78
|
+
本执行器是 `ctx.shell` seam 的沙箱 Service Provider:它继承 `dsh-bash-local` 的进程机制,通过 `ctx.sandbox.confine()` 等待每条命令的精确 `['bash', '-c', command]` argv 完成限制准备,再直接 spawn 返回的 argv。前台准备使用本地执行器与命令共享的 deadline;在 spawn 前超时不会声明 enforcement 事实。后台准备只跟随调用方信号。两条路径都在 spawn 前重新检查取消状态。由哪种平台 runner 限制命令、以及是否有 runner 可用,属于提供方职责;本包只负责 bash 侧:所选模式、强制执行完整度,以及结果上的拒绝分类。
|
|
79
79
|
|
|
80
80
|
### 源码地图
|
|
81
81
|
|
|
@@ -83,7 +83,7 @@ kind: "package-reference"
|
|
|
83
83
|
|---|---|
|
|
84
84
|
| [`src/index.ts`](src/index.ts) | 插件入口:`SandboxBashExecutor`、按进程保留事实、run/start 包装 |
|
|
85
85
|
| [`src/helpers.ts`](src/helpers.ts) | 拒绝、runner 失败与 runner spawn 失败分类 |
|
|
86
|
-
| — |
|
|
86
|
+
| — | 不发布运行时不变式伴生入口;分类可在结果中观察,且除归属 seam 所强制执行的约定外,本包不公开独立事件序列或可变数据关系。 |
|
|
87
87
|
| `tests/` | 跨 bwrap、Landlock 与 Seatbelt runner 演练的行为 |
|
|
88
88
|
|
|
89
89
|
### 主要流程
|
|
@@ -92,7 +92,7 @@ kind: "package-reference"
|
|
|
92
92
|
|
|
93
93
|
### 不变式
|
|
94
94
|
|
|
95
|
-
- **失败关闭**——受限模式没有可用 runner
|
|
95
|
+
- **失败关闭**——受限模式没有可用 runner 时以 `SANDBOX_UNAVAILABLE` 拒绝;受限策略绝不会出现无隔离直通。
|
|
96
96
|
- **seam 只报告拒绝**——本执行器从不授予权限;批准流程位于工具层。
|
|
97
97
|
- **按进程保留事实**——隔离事实在结算前按句柄保留,因为提供方可能在重叠调用之间改变强制执行方式。
|
|
98
98
|
- **只约束文件影响**——模式词汇只声称文件影响。
|
|
@@ -141,7 +141,7 @@ kind: "package-reference"
|
|
|
141
141
|
|
|
142
142
|
#### Token 影响
|
|
143
143
|
|
|
144
|
-
除普通输出外,正常允许的运行不会增加 token
|
|
144
|
+
除普通输出外,正常允许的运行不会增加 token。拒绝或失败会增加上述有条件标记,并保留到上下文压缩(context compaction)。
|
|
145
145
|
|
|
146
146
|
#### KV Cache 影响
|
|
147
147
|
|
|
@@ -151,7 +151,7 @@ kind: "package-reference"
|
|
|
151
151
|
|
|
152
152
|
#### 模型看到的内容
|
|
153
153
|
|
|
154
|
-
如果没有 runner 能强制执行受限模式,前台调用会传播来自 sandbox seam 的 `SANDBOX_UNAVAILABLE`
|
|
154
|
+
如果没有 runner 能强制执行受限模式,前台调用会传播来自 sandbox seam 的 `SANDBOX_UNAVAILABLE` 错误。当提供方拒绝带有 `ENOENT`/`EACCES` 路径或 syscall 证据并指向 `argv[0]` 时,会把原始错误作为 runner 失败详情;其他拒绝仍是与阶段无关的提供方错误。已结算的 runner 失败以匹配到的致命 stderr 行作为详情,并保留原始 stderr 收集结果;追加的 `Runner failure: <detail>` 是权威诊断,优先于通用的 `SANDBOX_UNAVAILABLE` 前缀。
|
|
155
155
|
|
|
156
156
|
#### Token 影响
|
|
157
157
|
|
|
@@ -170,7 +170,7 @@ kind: "package-reference"
|
|
|
170
170
|
|
|
171
171
|
- **限制只覆盖文件影响**——不提供网络限制和统一的进程可见性保证,因此这些模式不是通用安全沙箱。
|
|
172
172
|
- **拒绝从失败命令的 stderr 推断**——后端特征使该推断可跨平台使用,但包含相同特征的应用错误可能被分类为拒绝,也可能遗漏未出现在保留尾部中的拒绝。
|
|
173
|
-
- **异步观测到的后台 runner 失败没有即时错误通道**——它记录在已结算进程上,并在调用方用 `job_output`
|
|
173
|
+
- **异步观测到的后台 runner 失败没有即时错误通道**——它记录在已结算进程上,并在调用方用 `job_output` 读取通用任务时呈现;同步 subprocess throw 若指明 runner 路径,则会在发布句柄前拒绝 `start()`。
|
|
174
174
|
- **`danger-full-access` 有意绕过 `ctx.sandbox`**——它是显式无约束模式,不是更宽的沙箱 profile。
|
|
175
175
|
|
|
176
176
|
<a id="dev-note"></a>
|
|
@@ -179,6 +179,6 @@ kind: "package-reference"
|
|
|
179
179
|
<details>
|
|
180
180
|
<summary>维护者的工作上下文——点击展开</summary>
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
无。
|
|
183
183
|
|
|
184
184
|
</details>
|
package/lib/index.js
CHANGED
|
@@ -1,50 +1,7 @@
|
|
|
1
|
-
import { SandboxUnavailableError } from "@deepseek-ai/dsh-sandbox";
|
|
1
|
+
import { SandboxUnavailableError, classifyRunnerFailure, isRunnerSpawnFailure, matchesSignature, matchesSignature as matchesSignature$1 } from "@deepseek-ai/dsh-sandbox";
|
|
2
2
|
import { LocalBashExecutor } from "@deepseek-ai/dsh-bash-local";
|
|
3
|
-
import { accessSync, constants, statSync } from "node:fs";
|
|
4
3
|
//#region lib/types/helpers.js
|
|
5
4
|
/**
|
|
6
|
-
* Internal sandbox-result classification helpers.
|
|
7
|
-
*
|
|
8
|
-
* @module @deepseek-ai/dsh-bash-sandbox/helpers
|
|
9
|
-
*/
|
|
10
|
-
/** Node-local spawn codes proven to identify executable resolution or permission failure. */
|
|
11
|
-
const EXECUTABLE_SPAWN_CODES = new Set(["EACCES", "ENOENT"]);
|
|
12
|
-
/** Whether the caller-owned spawn cwd can be entered. */
|
|
13
|
-
function isUsableWorkdir(path) {
|
|
14
|
-
try {
|
|
15
|
-
if (!statSync(path).isDirectory()) return false;
|
|
16
|
-
accessSync(path, constants.X_OK);
|
|
17
|
-
return true;
|
|
18
|
-
} catch {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Attribute only Node ENOENT/EACCES failures whose error path equals argv[0]
|
|
24
|
-
* after independently ruling out the caller-owned cwd. A supplied error path
|
|
25
|
-
* must exactly identify the runner; without one, the syscall must. With a
|
|
26
|
-
* usable cwd, these codes describe resolution or execute permission for that
|
|
27
|
-
* argv[0] or its shebang interpreter.
|
|
28
|
-
* The workdir is checked at classification time, not atomically with spawn;
|
|
29
|
-
* concurrent path replacement may change attribution but cannot permit an
|
|
30
|
-
* unconfined execution.
|
|
31
|
-
* @param error - the original spawn rejection.
|
|
32
|
-
* @param runnerProgram - provider argv[0], the executable that establishes confinement.
|
|
33
|
-
* @param workdir - the caller-owned spawn cwd, checked independently for usability.
|
|
34
|
-
* @returns whether the rejection has executable-specific runner evidence.
|
|
35
|
-
*/
|
|
36
|
-
function isRunnerSpawnFailure(error, runnerProgram, workdir) {
|
|
37
|
-
if (runnerProgram === void 0 || !isUsableWorkdir(workdir)) return false;
|
|
38
|
-
if (typeof error !== "object" || error === null) return false;
|
|
39
|
-
const { code, path, syscall } = error;
|
|
40
|
-
if (typeof code !== "string" || !EXECUTABLE_SPAWN_CODES.has(code)) return false;
|
|
41
|
-
if (typeof syscall !== "string") return false;
|
|
42
|
-
const exactSyscall = `spawn ${runnerProgram}`;
|
|
43
|
-
if (path === void 0) return syscall === exactSyscall;
|
|
44
|
-
if (typeof path !== "string" || path.length === 0 || path !== runnerProgram) return false;
|
|
45
|
-
return syscall === "spawn" || syscall === exactSyscall;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
5
|
* Classify a failed run against the selected backend's denial dialect.
|
|
49
6
|
* @param result - settled foreground run.
|
|
50
7
|
* @param signatures - case-insensitive denial substrings from the active wrap.
|
|
@@ -53,42 +10,6 @@ function isRunnerSpawnFailure(error, runnerProgram, workdir) {
|
|
|
53
10
|
function classifyDenial(result, signatures) {
|
|
54
11
|
return matchesSignature(result.exitCode, result.stderr.text, signatures);
|
|
55
12
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Classify one settled process against the selected backend's structured
|
|
58
|
-
* runner-failure rules. Each rule requires a nonzero exit, its optional
|
|
59
|
-
* exit-code gate, and a fatal signature on one stderr line after exact
|
|
60
|
-
* informational lines are excluded.
|
|
61
|
-
* @param exitCode - process exit code; null means signal termination.
|
|
62
|
-
* @param stderr - collected stderr text, left unchanged.
|
|
63
|
-
* @param rules - structured runner-failure rules from the active wrap.
|
|
64
|
-
* @returns the first matching fatal line, or undefined when evidence is insufficient.
|
|
65
|
-
*/
|
|
66
|
-
function classifyRunnerFailure(exitCode, stderr, rules) {
|
|
67
|
-
if (exitCode === null || exitCode === 0) return void 0;
|
|
68
|
-
const lines = stderr.split(/\r?\n/);
|
|
69
|
-
for (const rule of rules) {
|
|
70
|
-
if (rule.allowedExitCodes !== void 0 && !rule.allowedExitCodes.includes(exitCode)) continue;
|
|
71
|
-
const informationalLines = new Set((rule.informationalLines ?? []).map((line) => line.toLowerCase()));
|
|
72
|
-
const fatalSignatures = rule.fatalSignatures.filter((signature) => signature.trim().length > 0).map((signature) => signature.toLowerCase());
|
|
73
|
-
for (const line of lines) {
|
|
74
|
-
const lowered = line.toLowerCase();
|
|
75
|
-
if (informationalLines.has(lowered)) continue;
|
|
76
|
-
if (fatalSignatures.some((signature) => lowered.includes(signature))) return { detail: line };
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Match a non-zero exit against case-insensitive stderr signatures.
|
|
82
|
-
* @param exitCode - process exit code; null means signal termination.
|
|
83
|
-
* @param stderr - collected stderr text.
|
|
84
|
-
* @param signatures - substrings identifying the selected backend's dialect.
|
|
85
|
-
* @returns whether this is a non-zero exit whose stderr matches a signature.
|
|
86
|
-
*/
|
|
87
|
-
function matchesSignature(exitCode, stderr, signatures) {
|
|
88
|
-
if (exitCode === null || exitCode === 0) return false;
|
|
89
|
-
const lowered = stderr.toLowerCase();
|
|
90
|
-
return signatures.some((signature) => lowered.includes(signature.toLowerCase()));
|
|
91
|
-
}
|
|
92
13
|
//#endregion
|
|
93
14
|
//#region lib/types/index.js
|
|
94
15
|
/**
|
|
@@ -151,37 +72,52 @@ var SandboxBashExecutor = class extends LocalBashExecutor {
|
|
|
151
72
|
denied: false
|
|
152
73
|
}
|
|
153
74
|
};
|
|
154
|
-
|
|
155
|
-
...policy,
|
|
156
|
-
mode
|
|
157
|
-
});
|
|
75
|
+
let confined;
|
|
158
76
|
let result;
|
|
77
|
+
let spawnRequested;
|
|
159
78
|
try {
|
|
160
|
-
result = await this.runArgv(spec,
|
|
79
|
+
({result, spawnRequested} = await this.runArgv(spec, async (signal) => {
|
|
80
|
+
const prepared = await this.confine(spec.command, {
|
|
81
|
+
...policy,
|
|
82
|
+
mode
|
|
83
|
+
}, signal);
|
|
84
|
+
signal.throwIfAborted();
|
|
85
|
+
confined = prepared;
|
|
86
|
+
return prepared.argv;
|
|
87
|
+
}));
|
|
161
88
|
} catch (error) {
|
|
162
89
|
if (spec.signal?.aborted === true) spec.signal.throwIfAborted();
|
|
163
|
-
if (isRunnerSpawnFailure(error, confined.argv[0], spec.workdir)) throw new SandboxUnavailableError(mode, String(error));
|
|
90
|
+
if (confined !== void 0 && isRunnerSpawnFailure(error, confined.argv[0], spec.workdir)) throw new SandboxUnavailableError(mode, String(error));
|
|
164
91
|
throw error;
|
|
165
92
|
}
|
|
166
|
-
|
|
93
|
+
if (!spawnRequested) return {
|
|
94
|
+
...result,
|
|
95
|
+
sandbox: {
|
|
96
|
+
mode,
|
|
97
|
+
denied: false
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const facts = confined;
|
|
101
|
+
const runnerFailure = classifyRunnerFailure(result.exitCode, result.stderr.text, facts.runnerFailureRules);
|
|
167
102
|
if (runnerFailure !== void 0) throw new SandboxUnavailableError(mode, runnerFailure.detail);
|
|
168
103
|
return {
|
|
169
104
|
...result,
|
|
170
105
|
sandbox: {
|
|
171
106
|
mode,
|
|
172
|
-
denied: classifyDenial(result,
|
|
173
|
-
enforcement:
|
|
107
|
+
denied: classifyDenial(result, facts.denialSignatures),
|
|
108
|
+
enforcement: facts.enforcement
|
|
174
109
|
}
|
|
175
110
|
};
|
|
176
111
|
}
|
|
177
|
-
start(spec) {
|
|
112
|
+
async start(spec) {
|
|
178
113
|
const policy = spec.sandboxPolicy;
|
|
179
114
|
const { mode } = policy;
|
|
180
115
|
if (mode === "danger-full-access") return super.start(spec);
|
|
181
|
-
const confined = this.confine(spec.command, {
|
|
116
|
+
const confined = await this.confine(spec.command, {
|
|
182
117
|
...policy,
|
|
183
118
|
mode
|
|
184
|
-
});
|
|
119
|
+
}, spec.signal);
|
|
120
|
+
spec.signal?.throwIfAborted();
|
|
185
121
|
let proc;
|
|
186
122
|
try {
|
|
187
123
|
proc = this.startArgv(spec, confined.argv);
|
|
@@ -211,7 +147,7 @@ var SandboxBashExecutor = class extends LocalBashExecutor {
|
|
|
211
147
|
const runnerFailed = providerRejected ? isRunnerSpawnFailure(providerError, facts.runnerProgram, facts.workdir) : classifyRunnerFailure(proc.exitCode, stderr, facts.runnerFailureRules) !== void 0;
|
|
212
148
|
proc.sandbox = {
|
|
213
149
|
mode: facts.mode,
|
|
214
|
-
denied: !runnerFailed && matchesSignature(proc.exitCode, stderr, facts.denialSignatures),
|
|
150
|
+
denied: !runnerFailed && matchesSignature$1(proc.exitCode, stderr, facts.denialSignatures),
|
|
215
151
|
enforcement: facts.enforcement,
|
|
216
152
|
...runnerFailed ? { runnerFailed } : {}
|
|
217
153
|
};
|
|
@@ -224,14 +160,15 @@ var SandboxBashExecutor = class extends LocalBashExecutor {
|
|
|
224
160
|
* executor's subprocess path.
|
|
225
161
|
* @param command - shell source for the confined inner `bash -c`.
|
|
226
162
|
* @param policy - resolved confined execution policy.
|
|
163
|
+
* @param signal - cancellation of confinement preparation.
|
|
227
164
|
* @returns the provider's exact argv and settlement-classification facts.
|
|
228
165
|
*/
|
|
229
|
-
confine(command, policy) {
|
|
166
|
+
confine(command, policy, signal) {
|
|
230
167
|
return this.ctx.sandbox.confine([
|
|
231
168
|
"bash",
|
|
232
169
|
"-c",
|
|
233
170
|
command
|
|
234
|
-
], policy);
|
|
171
|
+
], policy, signal);
|
|
235
172
|
}
|
|
236
173
|
};
|
|
237
174
|
//#endregion
|
package/lib/types/helpers.d.ts
CHANGED
|
@@ -1,30 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal sandbox-result classification helpers.
|
|
3
|
-
*
|
|
4
|
-
* @module @deepseek-ai/dsh-bash-sandbox/helpers
|
|
5
|
-
*/
|
|
1
|
+
/** Shell-result projection over shared sandbox diagnostics. */
|
|
6
2
|
import type { ShellRunResult } from '@deepseek-ai/dsh-shell';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Attribute only Node ENOENT/EACCES failures whose error path equals argv[0]
|
|
10
|
-
* after independently ruling out the caller-owned cwd. A supplied error path
|
|
11
|
-
* must exactly identify the runner; without one, the syscall must. With a
|
|
12
|
-
* usable cwd, these codes describe resolution or execute permission for that
|
|
13
|
-
* argv[0] or its shebang interpreter.
|
|
14
|
-
* The workdir is checked at classification time, not atomically with spawn;
|
|
15
|
-
* concurrent path replacement may change attribution but cannot permit an
|
|
16
|
-
* unconfined execution.
|
|
17
|
-
* @param error - the original spawn rejection.
|
|
18
|
-
* @param runnerProgram - provider argv[0], the executable that establishes confinement.
|
|
19
|
-
* @param workdir - the caller-owned spawn cwd, checked independently for usability.
|
|
20
|
-
* @returns whether the rejection has executable-specific runner evidence.
|
|
21
|
-
*/
|
|
22
|
-
export declare function isRunnerSpawnFailure(error: unknown, runnerProgram: string | undefined, workdir: string): boolean;
|
|
23
|
-
/** Fatal runner evidence retained for infrastructure-error detail. */
|
|
24
|
-
interface RunnerFailureMatch {
|
|
25
|
-
/** The original stderr line that matched a fatal signature. */
|
|
26
|
-
detail: string;
|
|
27
|
-
}
|
|
3
|
+
export { isRunnerSpawnFailure, classifyRunnerFailure, matchesSignature } from '@deepseek-ai/dsh-sandbox';
|
|
28
4
|
/**
|
|
29
5
|
* Classify a failed run against the selected backend's denial dialect.
|
|
30
6
|
* @param result - settled foreground run.
|
|
@@ -32,24 +8,4 @@ interface RunnerFailureMatch {
|
|
|
32
8
|
* @returns whether the failed run matches that denial dialect.
|
|
33
9
|
*/
|
|
34
10
|
export declare function classifyDenial(result: ShellRunResult, signatures: readonly string[]): boolean;
|
|
35
|
-
/**
|
|
36
|
-
* Classify one settled process against the selected backend's structured
|
|
37
|
-
* runner-failure rules. Each rule requires a nonzero exit, its optional
|
|
38
|
-
* exit-code gate, and a fatal signature on one stderr line after exact
|
|
39
|
-
* informational lines are excluded.
|
|
40
|
-
* @param exitCode - process exit code; null means signal termination.
|
|
41
|
-
* @param stderr - collected stderr text, left unchanged.
|
|
42
|
-
* @param rules - structured runner-failure rules from the active wrap.
|
|
43
|
-
* @returns the first matching fatal line, or undefined when evidence is insufficient.
|
|
44
|
-
*/
|
|
45
|
-
export declare function classifyRunnerFailure(exitCode: number | null, stderr: string, rules: readonly RunnerFailureRule[]): RunnerFailureMatch | undefined;
|
|
46
|
-
/**
|
|
47
|
-
* Match a non-zero exit against case-insensitive stderr signatures.
|
|
48
|
-
* @param exitCode - process exit code; null means signal termination.
|
|
49
|
-
* @param stderr - collected stderr text.
|
|
50
|
-
* @param signatures - substrings identifying the selected backend's dialect.
|
|
51
|
-
* @returns whether this is a non-zero exit whose stderr matches a signature.
|
|
52
|
-
*/
|
|
53
|
-
export declare function matchesSignature(exitCode: number | null, stderr: string, signatures: readonly string[]): boolean;
|
|
54
|
-
export {};
|
|
55
11
|
//# sourceMappingURL=helpers.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export declare class SandboxBashExecutor extends LocalBashExecutor {
|
|
|
48
48
|
*/
|
|
49
49
|
resolve(request: ShellExecRequest): ShellExecSpec;
|
|
50
50
|
run(spec: ShellExecSpec): Promise<ShellRunResult>;
|
|
51
|
-
start(spec: ShellExecSpec): ShellProcess
|
|
51
|
+
start(spec: ShellExecSpec): Promise<ShellProcess>;
|
|
52
52
|
/**
|
|
53
53
|
* Stamp per-process sandbox facts before `done` settles. Full-access processes
|
|
54
54
|
* have no facts; signal deaths are not denials.
|
|
@@ -60,6 +60,7 @@ export declare class SandboxBashExecutor extends LocalBashExecutor {
|
|
|
60
60
|
* executor's subprocess path.
|
|
61
61
|
* @param command - shell source for the confined inner `bash -c`.
|
|
62
62
|
* @param policy - resolved confined execution policy.
|
|
63
|
+
* @param signal - cancellation of confinement preparation.
|
|
63
64
|
* @returns the provider's exact argv and settlement-classification facts.
|
|
64
65
|
*/
|
|
65
66
|
private confine;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-bash-sandbox",
|
|
3
3
|
"description": "Sandbox-consuming implementation of the DeepSeek Harness bash executor seam (confines every command via ctx.sandbox, reports denial/enforcement result facts)",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.6-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,21 +27,21 @@
|
|
|
27
27
|
],
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@deepseek-ai/dsh-shell": "^0.1.
|
|
31
|
-
"@deepseek-ai/dsh-bash-local": "^0.1.
|
|
32
|
-
"@deepseek-ai/dsh-sandbox
|
|
33
|
-
"@deepseek-ai/dsh-sandbox": "^0.1.
|
|
30
|
+
"@deepseek-ai/dsh-shell": "^0.1.6-alpha.1",
|
|
31
|
+
"@deepseek-ai/dsh-bash-local": "^0.1.6-alpha.1",
|
|
32
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.1",
|
|
33
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.6-alpha.1",
|
|
34
34
|
"@deepseek-ai/cordis": "^4.0.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@deepseek-ai/dsh-shell": "^0.1.
|
|
38
|
-
"@deepseek-ai/dsh-
|
|
39
|
-
"@deepseek-ai/dsh-
|
|
40
|
-
"@deepseek-ai/dsh-sandbox
|
|
41
|
-
"@deepseek-ai/dsh-sandbox-
|
|
42
|
-
"@deepseek-ai/dsh-
|
|
37
|
+
"@deepseek-ai/dsh-shell": "^0.1.6-alpha.1",
|
|
38
|
+
"@deepseek-ai/dsh-bash-local": "^0.1.6-alpha.1",
|
|
39
|
+
"@deepseek-ai/dsh-subprocess-local": "^0.1.6-alpha.1",
|
|
40
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.1",
|
|
41
|
+
"@deepseek-ai/dsh-sandbox-local": "^0.1.6-alpha.1",
|
|
42
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.6-alpha.1",
|
|
43
43
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
44
44
|
"@deepseek-ai/node-addon-system": "^0.1.2",
|
|
45
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.
|
|
45
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.6-alpha.1"
|
|
46
46
|
}
|
|
47
47
|
}
|