opencode-landstrip 0.1.0 → 0.1.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/index.ts +46 -9
- package/package.json +7 -5
- package/sandbox.json +34 -2
package/index.ts
CHANGED
|
@@ -62,6 +62,8 @@ interface SandboxConfigOverrides {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
interface BashSandboxState {
|
|
65
|
+
originalCommand: string;
|
|
66
|
+
wrappedCommand: string;
|
|
65
67
|
policyDir: string;
|
|
66
68
|
port: number;
|
|
67
69
|
stop: () => Promise<void>;
|
|
@@ -97,7 +99,7 @@ const DEFAULT_CONFIG: SandboxConfig = {
|
|
|
97
99
|
},
|
|
98
100
|
filesystem: {
|
|
99
101
|
denyRead: ['/Users', '/home'],
|
|
100
|
-
allowRead: ['.', '~/.config/opencode', '~/.local', '~/.cargo'],
|
|
102
|
+
allowRead: ['.', '~/.config/opencode', '~/.config/git', '~/.gitconfig', '~/.local', '~/.cargo'],
|
|
101
103
|
allowWrite: ['.', '/tmp'],
|
|
102
104
|
denyWrite: ['.env', '.env.*', '*.pem', '*.key'],
|
|
103
105
|
},
|
|
@@ -621,6 +623,18 @@ function buildWrappedCommand(
|
|
|
621
623
|
return args.map(shellQuote).join(' ');
|
|
622
624
|
}
|
|
623
625
|
|
|
626
|
+
function isGeneratedWrappedCommand(config: SandboxConfig, command: string): boolean {
|
|
627
|
+
return (
|
|
628
|
+
command.startsWith(`${shellQuote(config.landstrip.command)} `) &&
|
|
629
|
+
command.includes(` ${shellQuote('-p')} `) &&
|
|
630
|
+
command.includes('opencode-landstrip-')
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function landstripDescription(description: string): string {
|
|
635
|
+
return description.endsWith(' (landstrip)') ? description : `${description} (landstrip)`;
|
|
636
|
+
}
|
|
637
|
+
|
|
624
638
|
function getToolPath(args: Record<string, unknown>): string | undefined {
|
|
625
639
|
const filePath = args.filePath ?? args.path;
|
|
626
640
|
return typeof filePath === 'string' ? filePath : undefined;
|
|
@@ -810,7 +824,24 @@ export default (async ({ client, directory }: PluginInput, options?: PluginOptio
|
|
|
810
824
|
config: SandboxConfig,
|
|
811
825
|
): Promise<void> {
|
|
812
826
|
if (typeof args.command !== 'string') return;
|
|
813
|
-
|
|
827
|
+
|
|
828
|
+
const existing = activeBash.get(callID);
|
|
829
|
+
if (existing) {
|
|
830
|
+
if (args.command === existing.originalCommand || args.command === existing.wrappedCommand) {
|
|
831
|
+
args.command = existing.wrappedCommand;
|
|
832
|
+
if (typeof args.description === 'string')
|
|
833
|
+
args.description = landstripDescription(args.description);
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
await cleanupBash(callID);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (isGeneratedWrappedCommand(config, args.command)) {
|
|
841
|
+
if (typeof args.description === 'string')
|
|
842
|
+
args.description = landstripDescription(args.description);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
814
845
|
|
|
815
846
|
const blockedDomain = firstBlockedDomain(args.command, config);
|
|
816
847
|
if (blockedDomain) {
|
|
@@ -834,19 +865,25 @@ export default (async ({ client, directory }: PluginInput, options?: PluginOptio
|
|
|
834
865
|
throw error;
|
|
835
866
|
}
|
|
836
867
|
|
|
868
|
+
const originalCommand = args.command;
|
|
869
|
+
const wrappedCommand = buildWrappedCommand(
|
|
870
|
+
config,
|
|
871
|
+
policy.path,
|
|
872
|
+
configuredShell ?? process.env.SHELL ?? '/bin/sh',
|
|
873
|
+
originalCommand,
|
|
874
|
+
);
|
|
875
|
+
|
|
837
876
|
activeBash.set(callID, {
|
|
877
|
+
originalCommand,
|
|
878
|
+
wrappedCommand,
|
|
838
879
|
policyDir: policy.dir,
|
|
839
880
|
port: proxy.port,
|
|
840
881
|
stop: proxy.stop,
|
|
841
882
|
});
|
|
842
883
|
|
|
843
|
-
args.command =
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
configuredShell ?? process.env.SHELL ?? '/bin/sh',
|
|
847
|
-
args.command,
|
|
848
|
-
);
|
|
849
|
-
if (typeof args.description === 'string') args.description = `${args.description} (landstrip)`;
|
|
884
|
+
args.command = wrappedCommand;
|
|
885
|
+
if (typeof args.description === 'string')
|
|
886
|
+
args.description = landstripDescription(args.description);
|
|
850
887
|
}
|
|
851
888
|
|
|
852
889
|
const hooks: Hooks = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-landstrip",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Landlock-based sandboxing for opencode with landstrip",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"landlock",
|
|
@@ -31,13 +31,15 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
|
-
"fmt": "oxfmt index.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md",
|
|
34
|
+
"fmt": "oxfmt index.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md test/*.test.mjs",
|
|
35
35
|
"lint": "oxlint index.ts",
|
|
36
36
|
"check": "tsc --noEmit",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"test": "node --test test/*.test.mjs",
|
|
38
|
+
"all": "npm run fmt && npm run lint && npm run check && npm test",
|
|
39
|
+
"ci:fmt": "oxfmt --check index.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md test/*.test.mjs",
|
|
39
40
|
"ci:lint": "npm run lint",
|
|
40
|
-
"ci:check": "npm run check"
|
|
41
|
+
"ci:check": "npm run check",
|
|
42
|
+
"ci:test": "npm test"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@opencode-ai/plugin": "^1.16.2",
|
package/sandbox.json
CHANGED
|
@@ -7,9 +7,15 @@
|
|
|
7
7
|
"allowedDomains": [
|
|
8
8
|
"github.com",
|
|
9
9
|
"*.github.com",
|
|
10
|
+
"api.github.com",
|
|
10
11
|
"raw.githubusercontent.com",
|
|
12
|
+
"objects.githubusercontent.com",
|
|
13
|
+
"codeload.github.com",
|
|
11
14
|
"registry.npmjs.org",
|
|
15
|
+
"npmjs.org",
|
|
12
16
|
"*.npmjs.org",
|
|
17
|
+
"nodejs.org",
|
|
18
|
+
"*.nodejs.org",
|
|
13
19
|
"crates.io",
|
|
14
20
|
"*.crates.io",
|
|
15
21
|
"static.crates.io"
|
|
@@ -18,8 +24,34 @@
|
|
|
18
24
|
},
|
|
19
25
|
"filesystem": {
|
|
20
26
|
"denyRead": ["/home"],
|
|
21
|
-
"allowRead": [
|
|
22
|
-
|
|
27
|
+
"allowRead": [
|
|
28
|
+
".",
|
|
29
|
+
"/tmp",
|
|
30
|
+
"/var/tmp",
|
|
31
|
+
"/dev/null",
|
|
32
|
+
"~/.config/opencode",
|
|
33
|
+
"~/.config/git",
|
|
34
|
+
"~/.gitconfig",
|
|
35
|
+
"~/.local",
|
|
36
|
+
"~/.cargo",
|
|
37
|
+
"~/.rustup",
|
|
38
|
+
"~/.npm",
|
|
39
|
+
"~/.cache",
|
|
40
|
+
"~/.bun",
|
|
41
|
+
"~/.node-gyp"
|
|
42
|
+
],
|
|
43
|
+
"allowWrite": [
|
|
44
|
+
".",
|
|
45
|
+
"/tmp",
|
|
46
|
+
"/var/tmp",
|
|
47
|
+
"/dev/null",
|
|
48
|
+
"~/.cargo",
|
|
49
|
+
"~/.rustup",
|
|
50
|
+
"~/.npm",
|
|
51
|
+
"~/.cache",
|
|
52
|
+
"~/.bun",
|
|
53
|
+
"~/.node-gyp"
|
|
54
|
+
],
|
|
23
55
|
"denyWrite": [".env", ".env.*", "*.pem", "*.key"]
|
|
24
56
|
}
|
|
25
57
|
}
|