opencode-swarm 7.81.2 → 7.81.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1 -1
- package/dist/index.js +23 -5
- package/dist/sandbox/linux/bubblewrap-executor.d.ts +2 -1
- package/dist/sandbox/macos/sandbox-exec-executor.d.ts +7 -6
- package/dist/sandbox/win32/restricted-environment-executor.d.ts +11 -1
- package/package.json +1 -1
- package/dist/sandbox/linux/edge-cases.d.ts +0 -89
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.81.
|
|
55
|
+
version: "7.81.3",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.81.
|
|
72
|
+
version: "7.81.3",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -28232,6 +28232,8 @@ class BubblewrapSandboxExecutor {
|
|
|
28232
28232
|
"--unshare-ipc",
|
|
28233
28233
|
"--die-with-parent",
|
|
28234
28234
|
"--new-session",
|
|
28235
|
+
"--cap-drop",
|
|
28236
|
+
"ALL",
|
|
28235
28237
|
...bindArgs,
|
|
28236
28238
|
"--dev",
|
|
28237
28239
|
"/dev",
|
|
@@ -28528,6 +28530,18 @@ function probeWindowsSandbox() {
|
|
|
28528
28530
|
function psStringEscape(s) {
|
|
28529
28531
|
return s.replace(/[`"$]/g, "`$&");
|
|
28530
28532
|
}
|
|
28533
|
+
function getSafeWindowsPath() {
|
|
28534
|
+
const raw = process.env.SystemRoot;
|
|
28535
|
+
const isValid = typeof raw === "string" && raw.length > 0 && /^[A-Za-z]:[\\/](?:[^\\/;"'<>|*?\r\n]+[\\/]?)*$/.test(raw);
|
|
28536
|
+
const sysRoot = isValid ? raw : "C:\\Windows";
|
|
28537
|
+
return `${sysRoot}\\System32;${sysRoot}`;
|
|
28538
|
+
}
|
|
28539
|
+
function isPowerShellNativeCommand(command) {
|
|
28540
|
+
return /^(?:Remove-Item|rm|del|erase|Copy-Item|cp|copy|Move-Item|mv|move|Rename-Item|ren|New-Item|ni|Get-Item|gi|Get-ChildItem|ls|dir|gci|Get-Content|cat|type|gc|Set-Content|sc|Add-Content|ac|Clear-Content|clc|Test-Path|Resolve-Path|Split-Path|Join-Path|Out-File|Get-Date)\b/i.test(command.trimStart());
|
|
28541
|
+
}
|
|
28542
|
+
function isSafePsCommandBody(command) {
|
|
28543
|
+
return !/[;&|`$()\r\n]/.test(command);
|
|
28544
|
+
}
|
|
28531
28545
|
function isPathInScopes(command, scopes) {
|
|
28532
28546
|
if (scopes.length === 0)
|
|
28533
28547
|
return true;
|
|
@@ -28597,9 +28611,13 @@ class WindowsSandboxExecutor {
|
|
|
28597
28611
|
if (!isPathInScopes(command, _allScopes)) {
|
|
28598
28612
|
throw new SandboxError("Command targets paths outside authorized scopes", "PATH_ESCAPE_SCOPE");
|
|
28599
28613
|
}
|
|
28600
|
-
|
|
28614
|
+
if (isPowerShellNativeCommand(command) && !isSafePsCommandBody(command)) {
|
|
28615
|
+
throw new SandboxError("PowerShell-native command body contains unsafe characters", "UNSAFE_PS_COMMAND");
|
|
28616
|
+
}
|
|
28617
|
+
const safePath = getSafeWindowsPath();
|
|
28601
28618
|
const escapedTemp = psStringEscape(temp);
|
|
28602
28619
|
const escapedCommand = psStringEscape(command);
|
|
28620
|
+
const commandExec = isPowerShellNativeCommand(command) ? `Invoke-Expression "${escapedCommand}"` : `cmd /c "${escapedCommand}"`;
|
|
28603
28621
|
const psScript = `
|
|
28604
28622
|
$ErrorActionPreference = 'Stop';
|
|
28605
28623
|
try {
|
|
@@ -28626,8 +28644,8 @@ try {
|
|
|
28626
28644
|
}
|
|
28627
28645
|
}
|
|
28628
28646
|
|
|
28629
|
-
# Execute the command via
|
|
28630
|
-
|
|
28647
|
+
# Execute the command — PS-native cmdlets via Invoke-Expression, others via the standard command interpreter
|
|
28648
|
+
${commandExec};
|
|
28631
28649
|
} catch {
|
|
28632
28650
|
Write-Error $_.Exception.Message;
|
|
28633
28651
|
exit 1;
|
|
@@ -28636,7 +28654,7 @@ try {
|
|
|
28636
28654
|
}
|
|
28637
28655
|
getEnvOverrides() {
|
|
28638
28656
|
return {
|
|
28639
|
-
PATH:
|
|
28657
|
+
PATH: getSafeWindowsPath(),
|
|
28640
28658
|
TEMP: null,
|
|
28641
28659
|
TMP: null,
|
|
28642
28660
|
LD_PRELOAD: null,
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Wraps shell commands with bwrap (Bubblewrap) to restrict process capabilities.
|
|
5
5
|
* Uses --bind to mount scope paths read-write, --tmpfs for /tmp, and --ro-bind
|
|
6
|
-
* for essential read-only system paths.
|
|
6
|
+
* for essential read-only system paths. Drops all capabilities via --cap-drop ALL
|
|
7
|
+
* for defense-in-depth within the user namespace.
|
|
7
8
|
*/
|
|
8
9
|
import { type SandboxExecutor } from '../executor';
|
|
9
10
|
/**
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* macOS sandbox-exec sandbox executor.
|
|
3
3
|
*
|
|
4
|
-
* Wraps shell commands with sandbox-exec(8) to
|
|
5
|
-
* using a profile-based deny-by-default policy.
|
|
4
|
+
* Wraps shell commands with sandbox-exec(8) to enforce file-write containment.
|
|
6
5
|
*
|
|
7
|
-
* Profile
|
|
6
|
+
* Profile scope:
|
|
7
|
+
* - Non-file operations (network, IPC, process creation, sysctl reads) are
|
|
8
|
+
* ALLOWED via `(allow default)`. This executor enforces file-write
|
|
9
|
+
* containment only — it is not a full-process sandbox.
|
|
8
10
|
* - Read-only access to essential system paths (/usr, /bin, /sbin, /lib)
|
|
9
|
-
* - Read-write access to each scope path
|
|
10
|
-
* -
|
|
11
|
-
* - Denies all other file writes
|
|
11
|
+
* - Read-write access to each scope path and the temp directory
|
|
12
|
+
* - All other file writes are denied
|
|
12
13
|
*/
|
|
13
14
|
import { type SandboxExecutor } from '../executor';
|
|
14
15
|
/**
|
|
@@ -73,13 +73,23 @@ export declare class WindowsSandboxExecutor implements SandboxExecutor {
|
|
|
73
73
|
* - Sets scoped temp directory (%TEMP%, %TMP%)
|
|
74
74
|
* - Restricts PATH to safe system paths only
|
|
75
75
|
* - Removes dangerous environment variables that could be used to bypass restrictions
|
|
76
|
-
* - Executes
|
|
76
|
+
* - Executes PowerShell-native cmdlets (filesystem cmdlets only) via Invoke-Expression,
|
|
77
|
+
* and all other commands via cmd /c inside a PowerShell script
|
|
78
|
+
*
|
|
79
|
+
* Safety checks applied before wrapping:
|
|
80
|
+
* - PowerShell escape patterns are rejected via detectPowerShellEscape
|
|
81
|
+
* - PowerShell-native commands are restricted to a filesystem-only cmdlet whitelist
|
|
82
|
+
* - PowerShell-native command bodies must not contain statement separators (;),
|
|
83
|
+
* call operator (&), pipelines (|), backtick escapes (`), variable references ($),
|
|
84
|
+
* subexpressions/parentheses, or newlines
|
|
77
85
|
*
|
|
78
86
|
* @param command - Raw shell command to execute inside the sandbox
|
|
79
87
|
* @param scopePaths - Additional scope paths to allow (merged with constructor scope)
|
|
80
88
|
* @param tempDir - Optional temp directory override
|
|
81
89
|
* @returns A PowerShell-wrapped command string ready for shell execution,
|
|
82
90
|
* or the raw command string when the sandbox is unavailable (passthrough mode)
|
|
91
|
+
* @throws {SandboxError} UNSAFE_PS_COMMAND when a PowerShell-native command body
|
|
92
|
+
* contains characters that enable command injection via Invoke-Expression
|
|
83
93
|
*/
|
|
84
94
|
wrapCommand(command: string, scopePaths: string[], tempDir?: string): string;
|
|
85
95
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.81.
|
|
3
|
+
"version": "7.81.3",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Edge case handling utilities for Bubblewrap sandbox.
|
|
3
|
-
*
|
|
4
|
-
* This module provides functions to detect and prevent:
|
|
5
|
-
* - Symlink escape attacks
|
|
6
|
-
* - /proc/self/fd access
|
|
7
|
-
* - io_uring bypass
|
|
8
|
-
* - Namespace escape
|
|
9
|
-
* - Hard-link creation
|
|
10
|
-
* - Rename/move across scope boundary
|
|
11
|
-
* - mmap interception
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* Check whether a path is a symlink and resolves to a location outside
|
|
15
|
-
* any of the configured scope paths.
|
|
16
|
-
*
|
|
17
|
-
* @param path - The path to check (may be a symlink)
|
|
18
|
-
* @param scopePaths - Array of absolute scope paths
|
|
19
|
-
* @returns true if the path is a symlink that escapes the sandbox
|
|
20
|
-
*/
|
|
21
|
-
export declare function detectSymlinkEscape(path: string, scopePaths: string[]): boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Check whether a path is under /proc/self/fd/, which provides
|
|
24
|
-
* file descriptor access that can bypass normal path checks.
|
|
25
|
-
*
|
|
26
|
-
* @param path - The path to check
|
|
27
|
-
* @returns true if the path is under /proc/self/fd/
|
|
28
|
-
*/
|
|
29
|
-
export declare function detectProcFdAccess(path: string): boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Detect whether io_uring is active on the system, which can be used
|
|
32
|
-
* to perform I/O operations that bypass the seccomp filter.
|
|
33
|
-
*
|
|
34
|
-
* Note: This is a detection function only — it does not prevent io_uring usage.
|
|
35
|
-
* Bubblewrap's --unshare-all combined with seccomp filtering can mitigate this.
|
|
36
|
-
*
|
|
37
|
-
* @returns true if io_uring appears to be active
|
|
38
|
-
*/
|
|
39
|
-
export declare function detectIoUringBypass(): boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Detect whether the current process is already running inside a user namespace.
|
|
42
|
-
*
|
|
43
|
-
* When a process is already inside a user namespace (rather than the initial
|
|
44
|
-
* namespace), it may have different privileges and isolation properties than
|
|
45
|
-
* expected. This can affect the security assumptions of a bubblewrap sandbox.
|
|
46
|
-
*
|
|
47
|
-
* @returns true if the current process is already inside a non-initial user namespace
|
|
48
|
-
*/
|
|
49
|
-
export declare function detectNamespaceEscape(): boolean;
|
|
50
|
-
/**
|
|
51
|
-
* Check whether a path operation would create a hard link that escapes
|
|
52
|
-
* the sandbox scope.
|
|
53
|
-
*
|
|
54
|
-
* Hard links can allow a file inside the sandbox to be linked to a location
|
|
55
|
-
* outside the sandbox, potentially bypassing containment.
|
|
56
|
-
*
|
|
57
|
-
* @param path - The path being linked to
|
|
58
|
-
* @param scopePaths - Array of absolute scope paths
|
|
59
|
-
* @returns true if creating a hard link at path would escape the sandbox
|
|
60
|
-
*/
|
|
61
|
-
export declare function detectHardLinkEscape(path: string, scopePaths: string[]): boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Alias for detectHardLinkEscape for API compatibility.
|
|
64
|
-
* @param path - The path being linked to
|
|
65
|
-
* @param scopePaths - Array of absolute scope paths
|
|
66
|
-
* @returns true if creating a hard link at path would escape the sandbox
|
|
67
|
-
*/
|
|
68
|
-
export declare function detectHardLinkCreation(path: string, scopePaths: string[]): boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Check whether a rename or move operation crosses a scope boundary.
|
|
71
|
-
*
|
|
72
|
-
* Moving a file from inside a scope path to outside violates containment.
|
|
73
|
-
*
|
|
74
|
-
* @param oldPath - The original path
|
|
75
|
-
* @param newPath - The destination path after rename/move
|
|
76
|
-
* @param scopePaths - Array of absolute scope paths
|
|
77
|
-
* @returns true if the rename crosses a scope boundary
|
|
78
|
-
*/
|
|
79
|
-
export declare function detectRenameAcrossBoundary(oldPath: string, newPath: string, scopePaths: string[]): boolean;
|
|
80
|
-
/**
|
|
81
|
-
* Check whether a path pattern suggests mmap interception attempts.
|
|
82
|
-
*
|
|
83
|
-
* mmap can be used to map device files or anonymous memory that bypasses
|
|
84
|
-
* normal file-based access controls.
|
|
85
|
-
*
|
|
86
|
-
* @param path - The path being accessed
|
|
87
|
-
* @returns true if the path suggests mmap interception
|
|
88
|
-
*/
|
|
89
|
-
export declare function detectMmapInterception(path: string): boolean;
|