pi-landstrip 0.14.0 → 0.14.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 +21 -35
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -90,7 +90,7 @@ interface LandstripBashCallbacks {
|
|
|
90
90
|
onErrorFd?: (data: Buffer) => void;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
const LANDSTRIP_VERSION = [0, 14,
|
|
93
|
+
const LANDSTRIP_VERSION = [0, 14, 5] as const;
|
|
94
94
|
const REQUIRED_LANDSTRIP_VERSION = LANDSTRIP_VERSION.join('.');
|
|
95
95
|
const SUPPORTED_PLATFORMS = new Set<NodeJS.Platform>(['linux', 'darwin', 'win32']);
|
|
96
96
|
|
|
@@ -198,7 +198,7 @@ function deepMerge(base: SandboxConfig, overrides: Partial<SandboxConfig>): Sand
|
|
|
198
198
|
|
|
199
199
|
function getConfigPaths(cwd: string): { globalPath: string; projectPath: string } {
|
|
200
200
|
return {
|
|
201
|
-
globalPath: join(
|
|
201
|
+
globalPath: join(getAgentDir(), 'sandbox.json'),
|
|
202
202
|
projectPath: join(cwd, '.pi', 'sandbox.json'),
|
|
203
203
|
};
|
|
204
204
|
}
|
|
@@ -391,40 +391,12 @@ function isFilesystemTrap(trap: LandstripTrap): trap is LandstripFilesystemTrap
|
|
|
391
391
|
return trap.kind === 'filesystem';
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
-
function
|
|
395
|
-
const paths: string[] = [];
|
|
396
|
-
// Split on whitespace, preserving quoted strings minimally
|
|
397
|
-
const tokens = command.match(/[^\s"']+|"[^"]*"|'[^']*'/g) ?? [];
|
|
398
|
-
for (const token of tokens) {
|
|
399
|
-
const clean = token.replace(/^["']|["']$/g, '').replace(/[,;]$/, '');
|
|
400
|
-
if (isPathLike(clean)) {
|
|
401
|
-
paths.push(clean);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return paths;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function extractBlockedPath(output: string, cwd: string, command?: string): string | null {
|
|
394
|
+
function extractBlockedPath(output: string, cwd: string): string | null {
|
|
408
395
|
const landstripErrors = parseLandstripTraps(output).filter(isFilesystemTrap);
|
|
409
396
|
if (landstripErrors.length > 0) {
|
|
410
397
|
return normalizeBlockedPath(landstripErrors[0].file, cwd);
|
|
411
398
|
}
|
|
412
399
|
|
|
413
|
-
// If landstrip reported an error but without a file field, try to
|
|
414
|
-
// extract the blocked path from the command itself.
|
|
415
|
-
if (landstripErrors.length > 0 && command) {
|
|
416
|
-
const config = loadConfig(cwd);
|
|
417
|
-
for (const candidate of extractCandidatePaths(command)) {
|
|
418
|
-
const resolved = normalizeBlockedPath(candidate, cwd);
|
|
419
|
-
if (
|
|
420
|
-
matchesPattern(resolved, config.filesystem.denyRead) ||
|
|
421
|
-
!matchesPattern(resolved, config.filesystem.allowRead)
|
|
422
|
-
) {
|
|
423
|
-
return resolved;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
400
|
return extractNativeDeniedPath(output, cwd);
|
|
429
401
|
}
|
|
430
402
|
|
|
@@ -982,8 +954,8 @@ export function createLandstripIntegration(
|
|
|
982
954
|
},
|
|
983
955
|
filesystem: {
|
|
984
956
|
denyRead: config.filesystem.denyRead,
|
|
985
|
-
allowRead:
|
|
986
|
-
allowWrite:
|
|
957
|
+
allowRead: getEffectiveAllowRead(cwd),
|
|
958
|
+
allowWrite: getEffectiveAllowWrite(cwd),
|
|
987
959
|
denyWrite: config.filesystem.denyWrite,
|
|
988
960
|
},
|
|
989
961
|
};
|
|
@@ -1019,10 +991,17 @@ export function createLandstripIntegration(
|
|
|
1019
991
|
return;
|
|
1020
992
|
}
|
|
1021
993
|
|
|
994
|
+
let settled = false;
|
|
1022
995
|
const upstream = connectNet(endpoint.port, endpoint.host, () => {
|
|
996
|
+
settled = true;
|
|
1023
997
|
client.write('HTTP/1.1 200 Connection Established\r\n\r\n');
|
|
1024
998
|
pipeSockets(client, upstream, rest);
|
|
1025
999
|
});
|
|
1000
|
+
upstream.once('error', () => {
|
|
1001
|
+
if (settled) return;
|
|
1002
|
+
settled = true;
|
|
1003
|
+
denyProxyRequest(client, '502 Bad Gateway');
|
|
1004
|
+
});
|
|
1026
1005
|
}
|
|
1027
1006
|
|
|
1028
1007
|
async function handleHttp(client: Socket, headerText: string, rest: Buffer): Promise<void> {
|
|
@@ -1061,10 +1040,17 @@ export function createLandstripIntegration(
|
|
|
1061
1040
|
const rewrittenHeader = lines
|
|
1062
1041
|
.filter((line) => !line.toLowerCase().startsWith('proxy-connection:'))
|
|
1063
1042
|
.join('\r\n');
|
|
1043
|
+
let settled = false;
|
|
1064
1044
|
const upstream = connectNet(port, url.hostname, () => {
|
|
1045
|
+
settled = true;
|
|
1065
1046
|
upstream.write(`${rewrittenHeader}\r\n\r\n`);
|
|
1066
1047
|
pipeSockets(client, upstream, rest);
|
|
1067
1048
|
});
|
|
1049
|
+
upstream.once('error', () => {
|
|
1050
|
+
if (settled) return;
|
|
1051
|
+
settled = true;
|
|
1052
|
+
denyProxyRequest(client, '502 Bad Gateway');
|
|
1053
|
+
});
|
|
1068
1054
|
}
|
|
1069
1055
|
|
|
1070
1056
|
function handleClient(client: Socket): void {
|
|
@@ -1215,8 +1201,8 @@ export function createLandstripIntegration(
|
|
|
1215
1201
|
const errorOutput = errorFdAcc || stderrAcc;
|
|
1216
1202
|
|
|
1217
1203
|
const blockedPath =
|
|
1218
|
-
extractBlockedPath(errorOutput, cwd
|
|
1219
|
-
(errorFdAcc ? extractBlockedPath(stderrAcc, cwd
|
|
1204
|
+
extractBlockedPath(errorOutput, cwd) ??
|
|
1205
|
+
(errorFdAcc ? extractBlockedPath(stderrAcc, cwd) : null);
|
|
1220
1206
|
const blockedWritePath =
|
|
1221
1207
|
extractBlockedWritePath(errorOutput, cwd) ??
|
|
1222
1208
|
(errorFdAcc ? extractBlockedWritePath(stderrAcc, cwd) : null);
|