@cloudflare/sandbox 0.0.0-ee8c772 → 0.0.0-eec5bb6
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/CHANGELOG.md +199 -0
- package/Dockerfile +96 -10
- package/README.md +806 -23
- package/container_src/bun.lock +76 -0
- package/container_src/circuit-breaker.ts +121 -0
- package/container_src/control-process.ts +784 -0
- package/container_src/handler/exec.ts +185 -0
- package/container_src/handler/file.ts +406 -0
- package/container_src/handler/git.ts +130 -0
- package/container_src/handler/ports.ts +314 -0
- package/container_src/handler/process.ts +568 -0
- package/container_src/handler/session.ts +92 -0
- package/container_src/index.ts +432 -2740
- package/container_src/interpreter-service.ts +276 -0
- package/container_src/isolation.ts +1038 -0
- package/container_src/mime-processor.ts +255 -0
- package/container_src/package.json +9 -0
- package/container_src/runtime/executors/javascript/node_executor.ts +123 -0
- package/container_src/runtime/executors/python/ipython_executor.py +338 -0
- package/container_src/runtime/executors/typescript/ts_executor.ts +138 -0
- package/container_src/runtime/process-pool.ts +464 -0
- package/container_src/shell-escape.ts +42 -0
- package/container_src/startup.sh +11 -0
- package/container_src/types.ts +131 -0
- package/package.json +6 -8
- package/src/client.ts +442 -1362
- package/src/errors.ts +219 -0
- package/src/index.ts +72 -126
- package/src/interpreter-client.ts +352 -0
- package/src/interpreter-types.ts +390 -0
- package/src/interpreter.ts +150 -0
- package/src/request-handler.ts +144 -0
- package/src/sandbox.ts +747 -0
- package/src/security.ts +113 -0
- package/src/sse-parser.ts +147 -0
- package/src/types.ts +502 -0
- package/tsconfig.json +1 -1
- package/tests/client.example.ts +0 -308
- package/tests/connection-test.ts +0 -81
- package/tests/simple-test.ts +0 -81
- package/tests/test1.ts +0 -281
- package/tests/test2.ts +0 -929
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"workspaces": {
|
|
4
|
+
"": {
|
|
5
|
+
"name": "sandbox-server",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"esbuild": "^0.21.5",
|
|
8
|
+
"uuid": "^9.0.1",
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@types/node": "^20.0.0",
|
|
12
|
+
"@types/uuid": "^9.0.7",
|
|
13
|
+
"typescript": "^5.3.0",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
"packages": {
|
|
18
|
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
|
19
|
+
|
|
20
|
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
|
21
|
+
|
|
22
|
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
|
|
23
|
+
|
|
24
|
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
|
|
25
|
+
|
|
26
|
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
|
27
|
+
|
|
28
|
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
|
|
29
|
+
|
|
30
|
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
|
|
31
|
+
|
|
32
|
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
|
|
33
|
+
|
|
34
|
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
|
|
35
|
+
|
|
36
|
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
|
|
37
|
+
|
|
38
|
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
|
|
39
|
+
|
|
40
|
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
|
|
41
|
+
|
|
42
|
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
|
|
43
|
+
|
|
44
|
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
|
|
45
|
+
|
|
46
|
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
|
|
47
|
+
|
|
48
|
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
|
|
49
|
+
|
|
50
|
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
|
|
51
|
+
|
|
52
|
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
|
|
53
|
+
|
|
54
|
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
|
|
55
|
+
|
|
56
|
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
|
|
57
|
+
|
|
58
|
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
|
|
59
|
+
|
|
60
|
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
|
|
61
|
+
|
|
62
|
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
|
|
63
|
+
|
|
64
|
+
"@types/node": ["@types/node@20.19.16", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-VS6TTONVdgwJwtJr7U+ghEjpfmQdqehLLpg/iMYGOd1+ilaFjdBJwFuPggJ4EAYPDCzWfDUHoIxyVnu+tOWVuQ=="],
|
|
65
|
+
|
|
66
|
+
"@types/uuid": ["@types/uuid@9.0.8", "", {}, "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="],
|
|
67
|
+
|
|
68
|
+
"esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
|
|
69
|
+
|
|
70
|
+
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
|
71
|
+
|
|
72
|
+
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
|
73
|
+
|
|
74
|
+
"uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker implementation to prevent cascading failures
|
|
3
|
+
*/
|
|
4
|
+
export class CircuitBreaker {
|
|
5
|
+
private failures = 0;
|
|
6
|
+
private lastFailure: number = 0;
|
|
7
|
+
private successCount = 0;
|
|
8
|
+
private state: "closed" | "open" | "half-open" = "closed";
|
|
9
|
+
|
|
10
|
+
// Configuration
|
|
11
|
+
private readonly threshold: number;
|
|
12
|
+
private readonly timeout: number;
|
|
13
|
+
private readonly halfOpenSuccessThreshold: number;
|
|
14
|
+
private readonly name: string;
|
|
15
|
+
|
|
16
|
+
constructor(options: {
|
|
17
|
+
name: string;
|
|
18
|
+
threshold?: number;
|
|
19
|
+
timeout?: number;
|
|
20
|
+
halfOpenSuccessThreshold?: number;
|
|
21
|
+
}) {
|
|
22
|
+
this.name = options.name;
|
|
23
|
+
this.threshold = options.threshold || 5;
|
|
24
|
+
this.timeout = options.timeout || 30000; // 30 seconds
|
|
25
|
+
this.halfOpenSuccessThreshold = options.halfOpenSuccessThreshold || 3;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Execute an operation with circuit breaker protection
|
|
30
|
+
*/
|
|
31
|
+
async execute<T>(operation: () => Promise<T>): Promise<T> {
|
|
32
|
+
// Check circuit state
|
|
33
|
+
if (this.state === "open") {
|
|
34
|
+
if (Date.now() - this.lastFailure > this.timeout) {
|
|
35
|
+
console.log(
|
|
36
|
+
`[CircuitBreaker ${this.name}] Transitioning from open to half-open`
|
|
37
|
+
);
|
|
38
|
+
this.state = "half-open";
|
|
39
|
+
this.successCount = 0;
|
|
40
|
+
} else {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Circuit breaker is open for ${this.name}. Retry after ${
|
|
43
|
+
this.timeout - (Date.now() - this.lastFailure)
|
|
44
|
+
}ms`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const result = await operation();
|
|
51
|
+
|
|
52
|
+
// Record success
|
|
53
|
+
if (this.state === "half-open") {
|
|
54
|
+
this.successCount++;
|
|
55
|
+
if (this.successCount >= this.halfOpenSuccessThreshold) {
|
|
56
|
+
console.log(
|
|
57
|
+
`[CircuitBreaker ${this.name}] Transitioning from half-open to closed`
|
|
58
|
+
);
|
|
59
|
+
this.state = "closed";
|
|
60
|
+
this.failures = 0;
|
|
61
|
+
}
|
|
62
|
+
} else if (this.state === "closed") {
|
|
63
|
+
// Reset failure count on success
|
|
64
|
+
this.failures = 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return result;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
this.recordFailure();
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Record a failure and update circuit state
|
|
76
|
+
*/
|
|
77
|
+
private recordFailure() {
|
|
78
|
+
this.failures++;
|
|
79
|
+
this.lastFailure = Date.now();
|
|
80
|
+
|
|
81
|
+
if (this.state === "half-open") {
|
|
82
|
+
console.log(
|
|
83
|
+
`[CircuitBreaker ${this.name}] Failure in half-open state, transitioning to open`
|
|
84
|
+
);
|
|
85
|
+
this.state = "open";
|
|
86
|
+
} else if (this.failures >= this.threshold) {
|
|
87
|
+
console.log(
|
|
88
|
+
`[CircuitBreaker ${this.name}] Threshold reached (${this.failures}/${this.threshold}), transitioning to open`
|
|
89
|
+
);
|
|
90
|
+
this.state = "open";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get current circuit breaker state
|
|
96
|
+
*/
|
|
97
|
+
getState(): {
|
|
98
|
+
state: string;
|
|
99
|
+
failures: number;
|
|
100
|
+
lastFailure: number;
|
|
101
|
+
isOpen: boolean;
|
|
102
|
+
} {
|
|
103
|
+
return {
|
|
104
|
+
state: this.state,
|
|
105
|
+
failures: this.failures,
|
|
106
|
+
lastFailure: this.lastFailure,
|
|
107
|
+
isOpen: this.state === "open",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Reset the circuit breaker
|
|
113
|
+
*/
|
|
114
|
+
reset() {
|
|
115
|
+
this.state = "closed";
|
|
116
|
+
this.failures = 0;
|
|
117
|
+
this.successCount = 0;
|
|
118
|
+
this.lastFailure = 0;
|
|
119
|
+
console.log(`[CircuitBreaker ${this.name}] Reset to closed state`);
|
|
120
|
+
}
|
|
121
|
+
}
|