@cloudflare/sandbox 0.0.9 → 0.1.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/Dockerfile +1 -14
  3. package/container_src/handler/exec.ts +337 -0
  4. package/container_src/handler/file.ts +844 -0
  5. package/container_src/handler/git.ts +182 -0
  6. package/container_src/handler/ports.ts +314 -0
  7. package/container_src/handler/process.ts +640 -0
  8. package/container_src/index.ts +82 -2973
  9. package/container_src/types.ts +103 -0
  10. package/dist/chunk-6THNBO4S.js +46 -0
  11. package/dist/chunk-6THNBO4S.js.map +1 -0
  12. package/dist/chunk-6UAWTJ5S.js +85 -0
  13. package/dist/chunk-6UAWTJ5S.js.map +1 -0
  14. package/dist/chunk-G4XT4SP7.js +638 -0
  15. package/dist/chunk-G4XT4SP7.js.map +1 -0
  16. package/dist/chunk-ISFOIYQC.js +585 -0
  17. package/dist/chunk-ISFOIYQC.js.map +1 -0
  18. package/dist/chunk-NNGBXDMY.js +89 -0
  19. package/dist/chunk-NNGBXDMY.js.map +1 -0
  20. package/dist/client-Da-mLX4p.d.ts +210 -0
  21. package/dist/client.d.ts +2 -1
  22. package/dist/client.js +3 -37
  23. package/dist/index.d.ts +3 -1
  24. package/dist/index.js +13 -3
  25. package/dist/request-handler.d.ts +2 -1
  26. package/dist/request-handler.js +4 -2
  27. package/dist/sandbox.d.ts +2 -1
  28. package/dist/sandbox.js +4 -2
  29. package/dist/security.d.ts +30 -0
  30. package/dist/security.js +13 -0
  31. package/dist/security.js.map +1 -0
  32. package/dist/sse-parser.d.ts +28 -0
  33. package/dist/sse-parser.js +11 -0
  34. package/dist/sse-parser.js.map +1 -0
  35. package/dist/types.d.ts +284 -0
  36. package/dist/types.js +19 -0
  37. package/dist/types.js.map +1 -0
  38. package/package.json +2 -7
  39. package/src/client.ts +235 -1286
  40. package/src/index.ts +6 -0
  41. package/src/request-handler.ts +69 -20
  42. package/src/sandbox.ts +463 -70
  43. package/src/security.ts +113 -0
  44. package/src/sse-parser.ts +147 -0
  45. package/src/types.ts +386 -0
  46. package/tsconfig.json +1 -1
  47. package/README.md +0 -65
  48. package/dist/chunk-4J5LQCCN.js +0 -1446
  49. package/dist/chunk-4J5LQCCN.js.map +0 -1
  50. package/dist/chunk-5SZ3RVJZ.js +0 -250
  51. package/dist/chunk-5SZ3RVJZ.js.map +0 -1
  52. package/dist/client-BuVjqV00.d.ts +0 -247
  53. package/tests/client.example.ts +0 -308
  54. package/tests/connection-test.ts +0 -81
  55. package/tests/simple-test.ts +0 -81
  56. package/tests/test1.ts +0 -281
  57. package/tests/test2.ts +0 -929
package/src/index.ts CHANGED
@@ -12,3 +12,9 @@ export {
12
12
  } from './request-handler';
13
13
 
14
14
  export { getSandbox, Sandbox } from "./sandbox";
15
+
16
+ // Export SSE parser for converting ReadableStream to AsyncIterable
17
+ export { asyncIterableToSSEStream, parseSSEStream, responseToAsyncIterable } from "./sse-parser";
18
+
19
+ // Export event types for streaming
20
+ export type { ExecEvent, LogEvent } from "./types";
@@ -1,4 +1,9 @@
1
1
  import { getSandbox, type Sandbox } from "./sandbox";
2
+ import {
3
+ logSecurityEvent,
4
+ sanitizeSandboxId,
5
+ validatePort
6
+ } from "./security";
2
7
 
3
8
  export interface SandboxEnv {
4
9
  Sandbox: DurableObjectNamespace<Sandbox>;
@@ -57,29 +62,74 @@ export async function proxyToSandbox<E extends SandboxEnv>(
57
62
  }
58
63
 
59
64
  function extractSandboxRoute(url: URL): RouteInfo | null {
60
- // Production: subdomain pattern {port}-{sandboxId}.{domain}
61
- const subdomainMatch = url.hostname.match(/^(\d+)-([a-zA-Z0-9-]+)\./);
62
- if (subdomainMatch) {
63
- return {
64
- port: parseInt(subdomainMatch[1]),
65
- sandboxId: subdomainMatch[2],
66
- path: url.pathname,
67
- };
68
- }
65
+ // Parse subdomain pattern: port-sandboxId.domain
66
+ const subdomainMatch = url.hostname.match(/^(\d{4,5})-([^.-][^.]*[^.-]|[^.-])\.(.+)$/);
69
67
 
70
- // Development: path pattern /preview/{port}/{sandboxId}/*
71
- if (isLocalhostPattern(url.hostname)) {
72
- const pathMatch = url.pathname.match(/^\/preview\/(\d+)\/([^/]+)(\/.*)?$/);
73
- if (pathMatch) {
74
- return {
75
- port: parseInt(pathMatch[1]),
76
- sandboxId: pathMatch[2],
77
- path: pathMatch[3] || "/",
78
- };
68
+ if (!subdomainMatch) {
69
+ // Log malformed subdomain attempts
70
+ if (url.hostname.includes('-') && url.hostname.includes('.')) {
71
+ logSecurityEvent('MALFORMED_SUBDOMAIN_ATTEMPT', {
72
+ hostname: url.hostname,
73
+ url: url.toString()
74
+ }, 'medium');
79
75
  }
76
+ return null;
77
+ }
78
+
79
+ const portStr = subdomainMatch[1];
80
+ const sandboxId = subdomainMatch[2];
81
+ const domain = subdomainMatch[3];
82
+
83
+ const port = parseInt(portStr, 10);
84
+ if (!validatePort(port)) {
85
+ logSecurityEvent('INVALID_PORT_IN_SUBDOMAIN', {
86
+ port,
87
+ portStr,
88
+ sandboxId,
89
+ hostname: url.hostname,
90
+ url: url.toString()
91
+ }, 'high');
92
+ return null;
93
+ }
94
+
95
+ let sanitizedSandboxId: string;
96
+ try {
97
+ sanitizedSandboxId = sanitizeSandboxId(sandboxId);
98
+ } catch (error) {
99
+ logSecurityEvent('INVALID_SANDBOX_ID_IN_SUBDOMAIN', {
100
+ sandboxId,
101
+ port,
102
+ hostname: url.hostname,
103
+ url: url.toString(),
104
+ error: error instanceof Error ? error.message : 'Unknown error'
105
+ }, 'high');
106
+ return null;
107
+ }
108
+
109
+ // DNS subdomain length limit is 63 characters
110
+ if (sandboxId.length > 63) {
111
+ logSecurityEvent('SANDBOX_ID_LENGTH_VIOLATION', {
112
+ sandboxId,
113
+ length: sandboxId.length,
114
+ port,
115
+ hostname: url.hostname
116
+ }, 'medium');
117
+ return null;
80
118
  }
81
119
 
82
- return null;
120
+ logSecurityEvent('SANDBOX_ROUTE_EXTRACTED', {
121
+ port,
122
+ sandboxId: sanitizedSandboxId,
123
+ domain,
124
+ path: url.pathname || "/",
125
+ hostname: url.hostname
126
+ }, 'low');
127
+
128
+ return {
129
+ port,
130
+ sandboxId: sanitizedSandboxId,
131
+ path: url.pathname || "/",
132
+ };
83
133
  }
84
134
 
85
135
  export function isLocalhostPattern(hostname: string): boolean {
@@ -92,4 +142,3 @@ export function isLocalhostPattern(hostname: string): boolean {
92
142
  hostPart === "0.0.0.0"
93
143
  );
94
144
  }
95
-