@aalis/plugin-code-sandbox-os 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox.d.ts +23 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +82 -0
- package/dist/sandbox.js.map +1 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ace Nyan <ace@acenyan.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context, PluginModule } from '@aalis/core';
|
|
2
|
+
export declare const name = "@aalis/plugin-code-sandbox-os";
|
|
3
|
+
export declare const displayName = "\u4EE3\u7801\u6C99\u7BB1\uFF08OS\uFF09";
|
|
4
|
+
export declare const provides: string[];
|
|
5
|
+
export declare const inject: {
|
|
6
|
+
required: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function apply(ctx: Context): Promise<void>;
|
|
9
|
+
declare const plugin: PluginModule;
|
|
10
|
+
export default plugin;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAU,YAAY,EAAE,MAAM,aAAa,CAAC;AAMjE,eAAO,MAAM,IAAI,kCAAkC,CAAC;AACpD,eAAO,MAAM,WAAW,2CAAa,CAAC;AACtC,eAAO,MAAM,QAAQ,UAAmB,CAAC;AACzC,eAAO,MAAM,MAAM;;CAElB,CAAC;AAmDF,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvD;AAED,QAAA,MAAM,MAAM,EAAE,YAA8B,CAAC;AAC7C,eAAe,MAAM,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @aalis/plugin-code-sandbox-os — code-sandbox 的 OS 原生实现
|
|
3
|
+
//
|
|
4
|
+
// Linux bubblewrap / macOS sandbox-exec。把不可信代码包成沙箱启动器命令后,
|
|
5
|
+
// **经现有 `process` 服务网关** spawn(不碰 process-api / process-local 的实现,
|
|
6
|
+
// 也不直接 import node:child_process / node:fs——OS 探测靠经网关功能性试跑)。
|
|
7
|
+
// ============================================================
|
|
8
|
+
import { createProcessGateway } from '@aalis/plugin-process-api';
|
|
9
|
+
import { wrapForSandbox } from './sandbox.js';
|
|
10
|
+
export const name = '@aalis/plugin-code-sandbox-os';
|
|
11
|
+
export const displayName = '代码沙箱(OS)';
|
|
12
|
+
export const provides = ['code-sandbox'];
|
|
13
|
+
export const inject = {
|
|
14
|
+
required: ['process'],
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 功能性探测:经 process 网关真正跑一次最小沙箱命令,跑通才算可用。
|
|
18
|
+
* 比「命令是否存在」更强——一次覆盖 存在性 + Linux unprivileged userns 是否真能用。
|
|
19
|
+
*/
|
|
20
|
+
async function probeBackend(proc, logger) {
|
|
21
|
+
const platform = process.platform;
|
|
22
|
+
try {
|
|
23
|
+
if (platform === 'darwin') {
|
|
24
|
+
await proc.execFile('sandbox-exec', ['-p', '(version 1) (allow default)', 'true'], { timeout: 5000 });
|
|
25
|
+
return 'seatbelt';
|
|
26
|
+
}
|
|
27
|
+
if (platform === 'linux') {
|
|
28
|
+
await proc.execFile('bwrap', ['--ro-bind', '/', '/', '--unshare-all', 'true'], { timeout: 5000 });
|
|
29
|
+
return 'bwrap';
|
|
30
|
+
}
|
|
31
|
+
logger.warn(`平台 ${platform} 暂无 OS 沙箱后端,code_runner auto 模式将 fail-closed`);
|
|
32
|
+
return 'none';
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// 启动器不存在 / 不可用(如 Linux 未安装 bwrap、或 unprivileged user namespaces 被禁)→ 无后端
|
|
36
|
+
logger.warn(`OS 沙箱后端探测失败(platform=${platform}):无可用沙箱,code_runner auto 模式将 fail-closed`);
|
|
37
|
+
return 'none';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
class OsCodeSandboxService {
|
|
41
|
+
proc;
|
|
42
|
+
_backend;
|
|
43
|
+
constructor(proc, _backend) {
|
|
44
|
+
this.proc = proc;
|
|
45
|
+
this._backend = _backend;
|
|
46
|
+
}
|
|
47
|
+
get available() {
|
|
48
|
+
return this._backend !== 'none';
|
|
49
|
+
}
|
|
50
|
+
get backend() {
|
|
51
|
+
return this._backend;
|
|
52
|
+
}
|
|
53
|
+
async run(req) {
|
|
54
|
+
if (this._backend === 'none') {
|
|
55
|
+
throw new Error('code-sandbox: 无可用后端,run() 不应被调用(调用方应先检查 available)');
|
|
56
|
+
}
|
|
57
|
+
const wrapped = wrapForSandbox(this._backend, req.policy, req.cmd, req.args, req.cwd, req.env ?? {});
|
|
58
|
+
// 经 process 网关 spawn 包好的启动器命令;env 已由 wrapper 的 --clearenv / env -i 注入白名单,
|
|
59
|
+
// 故此处不再传 env(外层启动器进程继承宿主 env 无妨,wrapper 已为内层不可信子进程清空)。
|
|
60
|
+
return this.proc.execFile(wrapped.cmd, wrapped.args, { cwd: req.cwd, timeout: req.timeout });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export async function apply(ctx) {
|
|
64
|
+
const logger = ctx.logger.child('code-sandbox-os');
|
|
65
|
+
const proc = createProcessGateway(ctx);
|
|
66
|
+
const backend = await probeBackend(proc, logger);
|
|
67
|
+
ctx.provide('code-sandbox', new OsCodeSandboxService(proc, backend));
|
|
68
|
+
logger.info(`code-sandbox-os 就绪(后端: ${backend === 'none' ? '无 —— 沙箱不可用,code_runner 将 fail-closed' : backend})`);
|
|
69
|
+
}
|
|
70
|
+
const plugin = { name, apply };
|
|
71
|
+
export default plugin;
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SandboxPolicy } from '@aalis/plugin-code-sandbox-api';
|
|
2
|
+
export type SandboxBackend = 'seatbelt' | 'bwrap' | 'none';
|
|
3
|
+
/**
|
|
4
|
+
* 生成 macOS Seatbelt (SBPL) profile:默认拒绝;放开 进程/读/常见系统调用;
|
|
5
|
+
* 写仅限 fsWrite + /dev 标准设备;网络按 policy。
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildSeatbeltProfile(policy: SandboxPolicy): string;
|
|
8
|
+
/** macOS:sandbox-exec -p profile env -i <allowlist> cmd args(env -i 清空 env 仅留白名单) */
|
|
9
|
+
export declare function buildSeatbeltArgs(policy: SandboxPolicy, cmd: string, args: readonly string[], env: Record<string, string | undefined>): {
|
|
10
|
+
cmd: string;
|
|
11
|
+
args: string[];
|
|
12
|
+
};
|
|
13
|
+
/** Linux:bwrap 只读绑根(可读+取解释器/库)、rw 绑写白名单、清 env 仅留白名单、按 policy 隔离网络。 */
|
|
14
|
+
export declare function buildBwrapArgs(policy: SandboxPolicy, cmd: string, args: readonly string[], cwd: string | undefined, env: Record<string, string | undefined>): {
|
|
15
|
+
cmd: string;
|
|
16
|
+
args: string[];
|
|
17
|
+
};
|
|
18
|
+
/** 按后端把 (cmd,args) 改写为「经沙箱启动器运行」。backend==='none' 不应调用(调用方先 fail-closed)。 */
|
|
19
|
+
export declare function wrapForSandbox(backend: SandboxBackend, policy: SandboxPolicy, cmd: string, args: readonly string[], cwd: string | undefined, env: Record<string, string | undefined>): {
|
|
20
|
+
cmd: string;
|
|
21
|
+
args: string[];
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAY3D;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAgBlE;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAIjC;AAED,sEAAsE;AACtE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAsBjC;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAIjC"}
|
package/dist/sandbox.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// sandbox.ts — OS 沙箱命令改写(纯逻辑,便于单测)
|
|
3
|
+
//
|
|
4
|
+
// 把不可信代码的子进程包到 OS 沙箱启动器里运行(仍 shell-free):
|
|
5
|
+
// - macOS → sandbox-exec -p '<SBPL>' env -i <allowlist> <cmd> <args>
|
|
6
|
+
// - Linux → bwrap <flags> --clearenv --setenv ... -- <cmd> <args>
|
|
7
|
+
// v1 语义:读放开(解释器需系统库)、写限定 fsWrite、网络粗粒度开关、env 仅白名单(防 secrets 泄漏)。
|
|
8
|
+
// 后端探测(功能性 probe)在 index.ts 经 process 网关做;本文件只做纯生成。
|
|
9
|
+
// ============================================================
|
|
10
|
+
/** 取 env 中非空键值对(保序),用于 --setenv / `env -i` */
|
|
11
|
+
function envPairs(env) {
|
|
12
|
+
return Object.entries(env).filter((e) => e[1] != null);
|
|
13
|
+
}
|
|
14
|
+
/** SBPL 字符串字面量转义 */
|
|
15
|
+
function sbplQuote(p) {
|
|
16
|
+
return `"${p.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 生成 macOS Seatbelt (SBPL) profile:默认拒绝;放开 进程/读/常见系统调用;
|
|
20
|
+
* 写仅限 fsWrite + /dev 标准设备;网络按 policy。
|
|
21
|
+
*/
|
|
22
|
+
export function buildSeatbeltProfile(policy) {
|
|
23
|
+
const lines = [
|
|
24
|
+
'(version 1)',
|
|
25
|
+
'(deny default)',
|
|
26
|
+
'(allow process-fork)',
|
|
27
|
+
'(allow process-exec)',
|
|
28
|
+
'(allow file-read*)',
|
|
29
|
+
'(allow sysctl-read)',
|
|
30
|
+
'(allow mach-lookup)',
|
|
31
|
+
'(allow ipc-posix-shm)',
|
|
32
|
+
'(allow signal)',
|
|
33
|
+
'(allow file-write-data (literal "/dev/null") (literal "/dev/stdout") (literal "/dev/stderr") (literal "/dev/dtracehelper") (literal "/dev/urandom"))',
|
|
34
|
+
];
|
|
35
|
+
for (const dir of policy.fsWrite)
|
|
36
|
+
lines.push(`(allow file-write* (subpath ${sbplQuote(dir)}))`);
|
|
37
|
+
lines.push(policy.network === 'allow' ? '(allow network*)' : '(deny network*)');
|
|
38
|
+
return `${lines.join('\n')}\n`;
|
|
39
|
+
}
|
|
40
|
+
/** macOS:sandbox-exec -p profile env -i <allowlist> cmd args(env -i 清空 env 仅留白名单) */
|
|
41
|
+
export function buildSeatbeltArgs(policy, cmd, args, env) {
|
|
42
|
+
const profile = buildSeatbeltProfile(policy);
|
|
43
|
+
const envArgs = envPairs(env).map(([k, v]) => `${k}=${v}`);
|
|
44
|
+
return { cmd: 'sandbox-exec', args: ['-p', profile, 'env', '-i', ...envArgs, cmd, ...args] };
|
|
45
|
+
}
|
|
46
|
+
/** Linux:bwrap 只读绑根(可读+取解释器/库)、rw 绑写白名单、清 env 仅留白名单、按 policy 隔离网络。 */
|
|
47
|
+
export function buildBwrapArgs(policy, cmd, args, cwd, env) {
|
|
48
|
+
const a = [
|
|
49
|
+
'--ro-bind',
|
|
50
|
+
'/',
|
|
51
|
+
'/',
|
|
52
|
+
'--dev',
|
|
53
|
+
'/dev',
|
|
54
|
+
'--proc',
|
|
55
|
+
'/proc',
|
|
56
|
+
'--tmpfs',
|
|
57
|
+
'/tmp', // 私有可写 /tmp;写白名单的 bind 在其后,故 /tmp 下的真实临时目录会被重新暴露为可写
|
|
58
|
+
'--unshare-all', // 含 net 命名空间隔离(断网)
|
|
59
|
+
'--die-with-parent',
|
|
60
|
+
'--new-session',
|
|
61
|
+
'--clearenv',
|
|
62
|
+
];
|
|
63
|
+
for (const [k, v] of envPairs(env))
|
|
64
|
+
a.push('--setenv', k, v);
|
|
65
|
+
if (policy.network === 'allow')
|
|
66
|
+
a.push('--share-net');
|
|
67
|
+
for (const dir of policy.fsWrite)
|
|
68
|
+
a.push('--bind', dir, dir);
|
|
69
|
+
if (cwd)
|
|
70
|
+
a.push('--chdir', cwd);
|
|
71
|
+
a.push('--', cmd, ...args);
|
|
72
|
+
return { cmd: 'bwrap', args: a };
|
|
73
|
+
}
|
|
74
|
+
/** 按后端把 (cmd,args) 改写为「经沙箱启动器运行」。backend==='none' 不应调用(调用方先 fail-closed)。 */
|
|
75
|
+
export function wrapForSandbox(backend, policy, cmd, args, cwd, env) {
|
|
76
|
+
if (backend === 'seatbelt')
|
|
77
|
+
return buildSeatbeltArgs(policy, cmd, args, env);
|
|
78
|
+
if (backend === 'bwrap')
|
|
79
|
+
return buildBwrapArgs(policy, cmd, args, cwd, env);
|
|
80
|
+
throw new Error(`不支持的沙箱后端: ${backend}`);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aalis/plugin-code-sandbox-os",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "代码沙箱(OS 原生):Linux bubblewrap / macOS sandbox-exec 隔离不可信代码执行",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"aalis",
|
|
9
|
+
"aalis-plugin"
|
|
10
|
+
],
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@aalis/plugin-process-api": "^0.4.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^22.0.0",
|
|
21
|
+
"typescript": "^5.7.0",
|
|
22
|
+
"@aalis/core": "0.4.0",
|
|
23
|
+
"@aalis/plugin-code-sandbox-api": "0.4.0"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@aalis/core": ">=0.2.0 <1.0.0"
|
|
27
|
+
},
|
|
28
|
+
"aalis": {
|
|
29
|
+
"service": {
|
|
30
|
+
"required": [
|
|
31
|
+
"process"
|
|
32
|
+
],
|
|
33
|
+
"provides": [
|
|
34
|
+
"code-sandbox"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc",
|
|
40
|
+
"dev": "tsc --watch"
|
|
41
|
+
}
|
|
42
|
+
}
|