@lobu/worker
Lobu worker runtime - run in your own Docker image or use our base image
Supply chain provenance
Status for the latest visible version.
Without SLSA provenance there is no cryptographic link between this tarball and the public source — the axios compromise (March 2026) relied on exactly this gap.
Maintainers
Keywords
Accepted risks
Findings the reviewer chose to accept rather than block on.
| Source | Rule | Reason | Accepted by | When |
|---|---|---|---|---|
| semgrep | semgrep:env-spread | AI (semgrep): Worker runtime intentionally forwards full env to child processes; pattern is expected and documented. | ai | |
| semgrep | semgrep:env-bulk-read | AI (semgrep): Same context: filtering process.env for child_process spawn is standard worker pattern. | ai | |
| phantom-deps | phantom-dep:owletto | AI (phantom-deps): owletto is a declared runtime dep; phantom-dep heuristic fires because it's used indirectly via config. | ai | |
| phantom-deps | phantom-dep:@lobu/owletto-openclaw | AI (phantom-deps): Same-org package used indirectly; phantom-dep false positive for this package. | ai | |
| semgrep | semgrep:base64-decode | AI (semgrep): Fires in test assertions verifying base64 encoding behavior; no malicious payload. | ai | |
| semgrep | semgrep:shady-links-raw-ip | AI (semgrep): Raw IP (127.0.0.1) appears only in a JSDoc comment as a localhost example URL. | ai | |
| semgrep | semgrep:etc-passwd-access | AI (semgrep): Fires in test files exercising the just-bash hostcat feature; not production credential harvesting. | ai |
Versions (showing 24 of 24)
| Version | Deps | Published |
|---|---|---|
| 11.0.0 | 11 / 2 | |
| 10.2.0 | 11 / 2 | |
| 10.1.0 | 11 / 2 | |
| 10.0.0 | 11 / 2 | |
| 9.4.1 | 11 / 2 | |
| 9.4.0 | 11 / 2 | |
| 9.3.0 | 11 / 2 | |
| 9.1.1 | 11 / 2 | |
| 9.1.0 | 11 / 2 | |
| 9.0.0 | 11 / 2 | |
| 8.0.0 | 11 / 2 | |
| 7.2.0 | 11 / 2 | |
| 7.1.0 | 11 / 2 | |
| 7.0.0 | 11 / 2 | |
| 6.1.1 | 11 / 2 | |
| 6.0.0 | 11 / 2 | |
| 5.0.0 | 11 / 2 | |
| 4.3.0 | 11 / 2 | |
| 4.2.0 | 13 / 2 | |
| 3.4.1 | 13 / 2 | |
| 3.2.0 | 13 / 2 | |
| 3.0.8 | 13 / 2 | |
| 3.0.7 | 13 / 2 | |
| 2.8.0 | 13 / 2 |
v11.0.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v10.2.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v10.1.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v10.0.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v9.4.1
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v9.4.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v9.3.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v9.1.1
17 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/a628d2a9b368a2f5bdafc5e574b80901b9f537e4/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v9.1.0
17 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/84430a13971a6622d474fb497747b66c4ef1f30c/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v9.0.0
17 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bf9c0114726954ebf81bec8b630d96737fc5aede/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v8.0.0
17 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/94d9c58edb4124c3a7e817642215b55672ca1966/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v7.2.0
17 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/daa209438132e955a730f4800ef6a4380a426d28/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v7.1.0
17 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/bd3001e4f868fc3ea2aac94084b2c90576ce690e/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v7.0.0
18 findingsAccessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/embedded-just-bash-bootstrap.test.ts#L56 54 | const ops = await createEmbeddedBashOps({ workspaceDir: workspace }); 55 | const chunks: string[] = []; > 56 | const result = await ops.exec("hostcat /etc/passwd", "/", { 57 | onData: (chunk) => chunks.push(chunk.toString()), 58 | timeout: 5,
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L283 281 | } 282 | > 283 | test("blocks /etc/passwd", async () => { 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L284 282 | 283 | test("blocks /etc/passwd", async () => { > 284 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 285 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 286 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L293 291 | }); 292 | > 293 | test("blocks ../../etc/passwd traversal", async () => { 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L294 292 | 293 | test("blocks ../../etc/passwd traversal", async () => { > 294 | const r = await runIn("/bin/sh", ["-c", "cat ../../etc/passwd"]); 295 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 296 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L298 296 | }); 297 | > 298 | test("blocks symlink-to-/etc/passwd", async () => { 299 | const r = await runIn("/bin/sh", [ 300 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L301 299 | const r = await runIn("/bin/sh", [ 300 | "-c", > 301 | "ln -sf /etc/passwd evil && cat evil", 302 | ]); 303 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L338 336 | 337 | test("argv injection: shell metacharacters not interpreted by execFile", async () => { > 338 | const r = await runIn("/bin/cat", ["hello.txt; cat /etc/passwd"]); 339 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 340 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L446 444 | } 445 | > 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L448 446 | test("blocks /etc/passwd outside the bind", async () => { 447 | // /etc is not bound, so the path doesn't exist inside the namespace at all. > 448 | const r = await runIn("/bin/cat", ["/etc/passwd"]); 449 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 450 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L458 456 | }); 457 | > 458 | test("blocks ../../etc/passwd traversal from /workspace", async () => { 459 | const r = await runIn("/bin/sh", [ 460 | "-c",
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L461 459 | const r = await runIn("/bin/sh", [ 460 | "-c", > 461 | "cd /workspace && cat ../../etc/passwd", 462 | ]); 463 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L467 465 | 466 | test("blocks symlink escape from workspace", async () => { > 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); 469 | // The symlink target /etc/passwd doesn't exist inside the namespace.
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L469 467 | fs.symlinkSync("/etc/passwd", path.join(workspace, "evil")); 468 | const r = await runIn("/bin/sh", ["-c", "cat /workspace/evil"]); > 469 | // The symlink target /etc/passwd doesn't exist inside the namespace. 470 | expect(r.ok && r.stdout.includes("root:")).toBe(false); 471 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/__tests__/exec-sandbox.test.ts#L533 531 | test("argv injection: shell metacharacters in execFile args don't escape", async () => { 532 | const r = await runIn("/bin/cat", [ > 533 | "/workspace/hello.txt; cat /etc/passwd", 534 | ]); 535 | expect(r.ok && r.stdout.includes("root:")).toBe(false);
Spreading entire process.env into an object — may capture all secrets Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/gateway/sse-client.ts#L582 580 | const proc = spawn("sh", ["-c", execCommand], { 581 | cwd: workingDir, > 582 | env: { ...process.env, ...execEnv }, 583 | stdio: ["ignore", "pipe", "pipe"], 584 | });
Accessing /etc/passwd or /etc/shadow — credential harvesting on Linux Source: https://github.com/lobu-ai/lobu/blob/597d8da67c3f94f37b9b2d68d90811878788eb19/src/shared/tool-implementations.ts#L232 230 | // Containment check: resolve the real path (following any symlinks) and 231 | // ensure it stays inside the worker's workspace. Without this, an agent > 232 | // can hand us `../../etc/passwd` (or a symlink that points there) and we 233 | // would happily upload it to the user. 234 | let filePath: string;
Package was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v6.1.1
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v6.0.0
1 findingPackage was published without Sigstore provenance. Consider requesting the maintainer enable provenance via CI/CD.
v4.2.0
1 findingPackage was published without Sigstore provenance. Only ~12% of npm packages have provenance, so this is common but not ideal.
v3.4.1
1 findingPublished via CI/CD with Sigstore attestation (predicate: https://slsa.dev/provenance/v1). This is the strongest supply chain integrity signal.
v3.2.0
1 findingPublished via CI/CD with Sigstore attestation (predicate: https://slsa.dev/provenance/v1). This is the strongest supply chain integrity signal.
v3.0.8
3 findingsSpreading entire process.env into an object — may capture all secrets Source: https://github.com/lobu-ai/lobu/blob/606a82ba9d7879a0a028fb63d1ab09e7e3f6326c/src/embedded/just-bash-bootstrap.ts#L100 98 | 99 | // Convert ctx.env (Map-like) to a plain Record for child_process > 100 | const envRecord: Record<string, string> = { ...process.env } as Record< 101 | string, 102 | string
Spreading entire process.env into an object — may capture all secrets Source: https://github.com/lobu-ai/lobu/blob/606a82ba9d7879a0a028fb63d1ab09e7e3f6326c/src/gateway/sse-client.ts#L581 579 | const proc = spawn("sh", ["-c", execCommand], { 580 | cwd: workingDir, > 581 | env: { ...process.env, ...execEnv }, 582 | stdio: ["ignore", "pipe", "pipe"], 583 | });
Package was published without Sigstore provenance. Only ~12% of npm packages have provenance, so this is common but not ideal.
v3.0.7
3 findingsSpreading entire process.env into an object — may capture all secrets Source: https://github.com/lobu-ai/lobu/blob/35af3938f5c7c311ab510ae13066a93034c0fe71/src/embedded/just-bash-bootstrap.ts#L100 98 | 99 | // Convert ctx.env (Map-like) to a plain Record for child_process > 100 | const envRecord: Record<string, string> = { ...process.env } as Record< 101 | string, 102 | string
Spreading entire process.env into an object — may capture all secrets Source: https://github.com/lobu-ai/lobu/blob/35af3938f5c7c311ab510ae13066a93034c0fe71/src/gateway/sse-client.ts#L581 579 | const proc = spawn("sh", ["-c", execCommand], { 580 | cwd: workingDir, > 581 | env: { ...process.env, ...execEnv }, 582 | stdio: ["ignore", "pipe", "pipe"], 583 | });
Package was published without Sigstore provenance. Only ~12% of npm packages have provenance, so this is common but not ideal.
v2.8.0
1 findingPackage was published without Sigstore provenance. Only ~12% of npm packages have provenance, so this is common but not ideal.