@cloudflare/sandbox 0.7.1 → 0.7.3
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/Dockerfile +30 -0
- package/dist/index.js +17 -9
- package/dist/index.js.map +1 -1
- package/dist/opencode/index.d.ts +4 -3
- package/dist/opencode/index.d.ts.map +1 -1
- package/dist/opencode/index.js +5 -3
- package/dist/opencode/index.js.map +1 -1
- package/dist/sandbox-CgjQQZGw.d.ts.map +1 -1
- package/package.json +4 -4
package/Dockerfile
CHANGED
|
@@ -201,3 +201,33 @@ ENV TYPESCRIPT_POOL_MIN_SIZE=3
|
|
|
201
201
|
EXPOSE 4096
|
|
202
202
|
|
|
203
203
|
ENTRYPOINT ["/container-server/sandbox"]
|
|
204
|
+
|
|
205
|
+
# ============================================================================
|
|
206
|
+
# Stage 5d: Musl image - Alpine-based with musl-linked binary
|
|
207
|
+
# ============================================================================
|
|
208
|
+
FROM alpine:3.21 AS musl
|
|
209
|
+
|
|
210
|
+
ARG SANDBOX_VERSION=unknown
|
|
211
|
+
|
|
212
|
+
ENV SANDBOX_VERSION=${SANDBOX_VERSION}
|
|
213
|
+
|
|
214
|
+
RUN apk add --no-cache bash file git ca-certificates curl libstdc++ libgcc s3fs-fuse fuse
|
|
215
|
+
|
|
216
|
+
RUN sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
|
|
217
|
+
|
|
218
|
+
COPY --from=builder /app/packages/sandbox-container/dist/sandbox-musl /container-server/sandbox
|
|
219
|
+
|
|
220
|
+
WORKDIR /container-server
|
|
221
|
+
|
|
222
|
+
COPY --from=builder /app/packages/sandbox-container/dist/runtime/executors/javascript/node_executor.js ./dist/runtime/executors/javascript/
|
|
223
|
+
COPY --from=builder /app/packages/sandbox-container/dist/index.js ./dist/
|
|
224
|
+
|
|
225
|
+
RUN mkdir -p /workspace
|
|
226
|
+
|
|
227
|
+
EXPOSE 3000
|
|
228
|
+
|
|
229
|
+
ENV PYTHON_POOL_MIN_SIZE=0
|
|
230
|
+
ENV JAVASCRIPT_POOL_MIN_SIZE=0
|
|
231
|
+
ENV TYPESCRIPT_POOL_MIN_SIZE=0
|
|
232
|
+
|
|
233
|
+
ENTRYPOINT ["/container-server/sandbox"]
|
package/dist/index.js
CHANGED
|
@@ -2089,13 +2089,16 @@ var SecurityError = class extends Error {
|
|
|
2089
2089
|
}
|
|
2090
2090
|
};
|
|
2091
2091
|
/**
|
|
2092
|
-
* Validates port numbers for sandbox services
|
|
2093
|
-
*
|
|
2092
|
+
* Validates port numbers for sandbox services.
|
|
2093
|
+
*
|
|
2094
|
+
* Rules:
|
|
2095
|
+
* - Range: 1024-65535 (privileged ports require root, which containers don't have)
|
|
2096
|
+
* - Reserved: 3000 (sandbox control plane)
|
|
2094
2097
|
*/
|
|
2095
2098
|
function validatePort(port) {
|
|
2096
2099
|
if (!Number.isInteger(port)) return false;
|
|
2097
2100
|
if (port < 1024 || port > 65535) return false;
|
|
2098
|
-
if ([3e3
|
|
2101
|
+
if ([3e3].includes(port)) return false;
|
|
2099
2102
|
return true;
|
|
2100
2103
|
}
|
|
2101
2104
|
/**
|
|
@@ -2564,7 +2567,7 @@ function buildS3fsSource(bucket, prefix) {
|
|
|
2564
2567
|
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
2565
2568
|
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
2566
2569
|
*/
|
|
2567
|
-
const SDK_VERSION = "0.7.
|
|
2570
|
+
const SDK_VERSION = "0.7.3";
|
|
2568
2571
|
|
|
2569
2572
|
//#endregion
|
|
2570
2573
|
//#region src/sandbox.ts
|
|
@@ -2581,6 +2584,7 @@ function getSandbox(ns, id, options) {
|
|
|
2581
2584
|
if (options?.containerTimeouts) stub.setContainerTimeouts(options.containerTimeouts);
|
|
2582
2585
|
const defaultSessionId = `sandbox-${effectiveId}`;
|
|
2583
2586
|
const enhancedMethods = {
|
|
2587
|
+
fetch: (request) => stub.fetch(request),
|
|
2584
2588
|
createSession: async (opts) => {
|
|
2585
2589
|
return enhanceSession(stub, await stub.createSession(opts));
|
|
2586
2590
|
},
|
|
@@ -2603,7 +2607,7 @@ function enhanceSession(stub, rpcSession) {
|
|
|
2603
2607
|
}
|
|
2604
2608
|
function connect(stub) {
|
|
2605
2609
|
return async (request, port) => {
|
|
2606
|
-
if (!validatePort(port)) throw new SecurityError(`Invalid
|
|
2610
|
+
if (!validatePort(port)) throw new SecurityError(`Invalid port number: ${port}. Must be 1024-65535, excluding 3000 (sandbox control plane).`);
|
|
2607
2611
|
const portSwitchedRequest = switchPort(request, port);
|
|
2608
2612
|
return await stub.fetch(portSwitchedRequest);
|
|
2609
2613
|
};
|
|
@@ -3668,6 +3672,7 @@ var Sandbox = class extends Container {
|
|
|
3668
3672
|
* // url: https://8080-sandbox-id-my-token-v1.example.com
|
|
3669
3673
|
*/
|
|
3670
3674
|
async exposePort(port, options) {
|
|
3675
|
+
if (!validatePort(port)) throw new SecurityError(`Invalid port number: ${port}. Must be 1024-65535, excluding 3000 (sandbox control plane).`);
|
|
3671
3676
|
if (options.hostname.endsWith(".workers.dev")) throw new CustomDomainRequiredError({
|
|
3672
3677
|
code: ErrorCode.CUSTOM_DOMAIN_REQUIRED,
|
|
3673
3678
|
message: `Port exposure requires a custom domain. .workers.dev domains do not support wildcard subdomains required for port proxying.`,
|
|
@@ -3695,7 +3700,7 @@ var Sandbox = class extends Container {
|
|
|
3695
3700
|
};
|
|
3696
3701
|
}
|
|
3697
3702
|
async unexposePort(port) {
|
|
3698
|
-
if (!validatePort(port)) throw new SecurityError(`Invalid port number: ${port}. Must be
|
|
3703
|
+
if (!validatePort(port)) throw new SecurityError(`Invalid port number: ${port}. Must be 1024-65535, excluding 3000 (sandbox control plane).`);
|
|
3699
3704
|
const sessionId = await this.ensureDefaultSession();
|
|
3700
3705
|
await this.client.ports.unexposePort(port, sessionId);
|
|
3701
3706
|
const tokens = await this.ctx.storage.get("portTokens") || {};
|
|
@@ -3735,11 +3740,14 @@ var Sandbox = class extends Container {
|
|
|
3735
3740
|
this.logger.error("Port is exposed but has no token - bug detected", void 0, { port });
|
|
3736
3741
|
return false;
|
|
3737
3742
|
}
|
|
3738
|
-
if (storedToken.length !== token.length) return false;
|
|
3739
3743
|
const encoder = new TextEncoder();
|
|
3740
3744
|
const a = encoder.encode(storedToken);
|
|
3741
3745
|
const b = encoder.encode(token);
|
|
3742
|
-
|
|
3746
|
+
try {
|
|
3747
|
+
return crypto.subtle.timingSafeEqual(a, b);
|
|
3748
|
+
} catch {
|
|
3749
|
+
return false;
|
|
3750
|
+
}
|
|
3743
3751
|
}
|
|
3744
3752
|
validateCustomToken(token) {
|
|
3745
3753
|
if (token.length === 0) throw new SecurityError(`Custom token cannot be empty.`);
|
|
@@ -3752,7 +3760,7 @@ var Sandbox = class extends Container {
|
|
|
3752
3760
|
return btoa(String.fromCharCode(...array)).replace(/\+/g, "_").replace(/\//g, "_").replace(/=/g, "").toLowerCase();
|
|
3753
3761
|
}
|
|
3754
3762
|
constructPreviewUrl(port, sandboxId, hostname, token) {
|
|
3755
|
-
if (!validatePort(port)) throw new SecurityError(`Invalid port number: ${port}. Must be
|
|
3763
|
+
if (!validatePort(port)) throw new SecurityError(`Invalid port number: ${port}. Must be 1024-65535, excluding 3000 (sandbox control plane).`);
|
|
3756
3764
|
const effectiveId = this.sandboxName || sandboxId;
|
|
3757
3765
|
const hasUppercase = /[A-Z]/.test(effectiveId);
|
|
3758
3766
|
if (!this.normalizeId && hasUppercase) throw new SecurityError(`Preview URLs require lowercase sandbox IDs. Your ID "${effectiveId}" contains uppercase letters.\n\nTo fix this:\n1. Create a new sandbox with: getSandbox(ns, "${effectiveId}", { normalizeId: true })\n2. This will create a sandbox with ID: "${effectiveId.toLowerCase()}"\n\nNote: Due to DNS case-insensitivity, IDs with uppercase letters cannot be used with preview URLs.`);
|