|
1 | | -# Sandboxed Node TODOs |
| 1 | +# Secure Exec TODOs |
2 | 2 |
|
3 | | -## High level |
| 3 | +This file tracks the active implementation backlog only. |
| 4 | +Resolved work should stay in OpenSpec archives and `docs-internal/friction.md` instead of remaining here as unchecked debt. |
4 | 5 |
|
5 | | -- Review the node driver |
6 | | -- Plan desired minimal driver that we'll use in rivet |
7 | | -- Add codemode example |
8 | | -- Add just-bash example |
9 | | -- Test with |
10 | | - - Pi |
11 | | - - Express |
12 | | - - Hono |
13 | | - - ??? |
| 6 | +Priority order is: |
| 7 | +1. Security and host-protection gaps |
| 8 | +2. Compatibility bugs and missing platform behavior |
| 9 | +3. Maintainability and performance follow-ups |
| 10 | +4. Examples, validation breadth, and product-shaping work |
14 | 11 |
|
15 | | -## Todo |
| 12 | +## Priority 0: Security and Host Protection |
16 | 13 |
|
17 | | -- [x] Remove all `@hono/node-server` bridge integration and load it only from sandboxed `node_modules`. |
18 | | - - Remove bridge module and exports (`packages/secure-exec/src/bridge/hono-node-server.ts`, `packages/secure-exec/src/bridge/index.ts`). |
19 | | - - Remove `@hono/node-server` special-cases in runtime resolution/execution (`packages/secure-exec/src/index.ts`, `packages/secure-exec/src/shared/require-setup.ts`). |
20 | | - - Remove `honoServe`/`honoClose` from adapter/types if no longer needed (`packages/secure-exec/src/types.ts`, `packages/secure-exec/src/shared/permissions.ts`, `packages/secure-exec/src/node/driver.ts`). |
| 14 | +- [ ] Finish end-to-end payload guards for remaining browser/bridge paths. |
| 15 | + - Node isolate execution now enforces JSON/base64 payload limits, but browser worker paths and remaining bridge `JSON.parse(...)` callsites still need equivalent bounds. |
| 16 | + - Files: `packages/secure-exec/src/browser/worker.ts`, `packages/secure-exec/src/bridge/*.ts` |
21 | 17 |
|
22 | | -- [x] Implement Node built-in HTTP server bridging (`http.createServer`) without third-party module bridges. |
23 | | - - Add server listen/close/address request-dispatch bridge hooks in runtime setup (`packages/secure-exec/src/index.ts`). |
24 | | - - Implement server-side compatibility in network bridge (`packages/secure-exec/src/bridge/network.ts`). |
25 | | - - Add Node driver implementation backed by `node:http` (`packages/secure-exec/src/node/driver.ts`, `packages/secure-exec/src/types.ts`, `packages/secure-exec/src/shared/permissions.ts`). |
| 18 | +- [ ] Add global host resource budgets. |
| 19 | + - Bound output bytes, bridge-call rate, timer count, and child-process count so hostile workloads cannot amplify host CPU or memory usage. |
| 20 | + - Files: `packages/secure-exec/src/node/execution-driver.ts`, `packages/secure-exec/src/bridge/process.ts`, `packages/secure-exec/src/shared/permissions.ts` |
26 | 21 |
|
27 | | -- [x] Expose host-side request path to sandbox servers via `sandbox.network.fetch(...)`. |
28 | | - - Provide a NodeRuntime-level network facade and document concurrent run/fetch pattern (`packages/secure-exec/src/index.ts`, `README.md`, `examples/hono/README.md`). |
29 | | - - Validate end-to-end from loader to runner (`examples/hono/loader/src/index.ts`, `examples/hono/runner/src/index.ts`). |
30 | | - |
31 | | -- [x] Fix `run()` ESM semantics to match docs (return module exports/default instead of evaluation result). |
32 | | - - Fix: `runESM` now returns copied entry-module namespace exports (default + named) after evaluation. |
33 | | - - `packages/secure-exec/src/index.ts`, `packages/secure-exec/tests/index.test.ts` |
34 | | - |
35 | | -- [x] Fix dynamic import execution semantics so imports are not eagerly evaluated before user code. |
36 | | - - Fix: precompile step now resolves/compiles only; instantiate/evaluate occur on first `import()` reach. |
37 | | - - `packages/secure-exec/src/index.ts`, `packages/secure-exec/tests/index.test.ts` |
38 | | - |
39 | | -- [x] Remove brittle require-path hacks/monkeypatches and replace with minimal, explicit compatibility behavior. |
40 | | - - Current hacks include `chalk`, `supports-color`, `tty`, `constants`, `v8`, and `util/url/path` patching. |
41 | | - - `packages/secure-exec/src/shared/require-setup.ts` |
42 | | - |
43 | | -- [x] Decide and enforce sandbox permission default model (allow-by-default vs deny-by-default); tighten if strict mode is desired. |
44 | | - - Fixed by flipping permission checks and env filtering to deny-by-default, and by exporting explicit `allowAll*` helpers for opt-in access. |
45 | | - - `packages/secure-exec/src/shared/permissions.ts` |
46 | | - |
47 | | -- [x] Make console capture robust for circular objects (avoid `JSON.stringify` throw paths in logging). |
48 | | - - `packages/secure-exec/src/index.ts` |
49 | | - |
50 | | -- [x] Reconcile `docs/node-compatability.mdx` with current runtime behavior. |
51 | | - - Fix: completed in `codify-stdlib-support-policy` (remove stale third-party bridge notes, align `http`/`https`/`http2` sections, add support tiers). |
52 | | - |
53 | | -- [x] Close or explicitly codify missing `fs` APIs listed in compatibility docs. |
54 | | - - Fix: completed in `codify-stdlib-support-policy` (`access`/`realpath` documented as implemented; missing APIs now use deterministic unsupported errors). |
55 | | - |
56 | | -- [x] Decide `child_process.fork()` support level. |
57 | | - - Fix: completed in `codify-stdlib-support-policy` (`fork` marked unsupported with deterministic `child_process.fork is not supported in sandbox` error). |
58 | | - |
59 | | -- [x] Tighten crypto support policy and implementation. |
60 | | - - Fix: completed in `codify-stdlib-support-policy` (explicit insecurity warning for `getRandomValues`, deterministic `crypto.subtle.*` unsupported errors, tiered policy documented). |
61 | | - |
62 | | -- [x] Track unimplemented core modules from compatibility docs as explicit product decisions. |
63 | | - - Fix: completed in `codify-stdlib-support-policy` (Tier 4 Deferred vs Tier 5 Unsupported classifications with rationale and runtime policy). |
| 22 | +- [ ] Cap and hard-fail child-process output buffering in sync APIs. |
| 23 | + - `spawnSync`/`execSync` paths still need deterministic output caps rather than unbounded accumulation. |
| 24 | + - Files: `packages/secure-exec/src/node/execution-driver.ts`, `packages/secure-exec/src/bridge/child-process.ts` |
64 | 25 |
|
65 | | -## Security & Hardening |
| 26 | +- [ ] Ensure child-process sessions are always cleaned up on timeout, dispose, and error paths. |
| 27 | + - Session-map leaks will keep host resources alive after sandbox failure paths. |
| 28 | + - Files: `packages/secure-exec/src/node/execution-driver.ts` |
66 | 29 |
|
67 | | -- [x] Filter Python `exec(..., { env })` overrides through `permissions.env`. |
68 | | - - Fix: `PyodideRuntimeDriver.exec()` now applies the shared `filterEnv(...)` gate before env overrides reach the worker, and runtime-driver tests cover both denied-by-default and explicitly-allowed cases. |
69 | | - - `packages/secure-exec/src/python/driver.ts`, `packages/secure-exec/tests/runtime-driver/python.test.ts` |
| 30 | +- [ ] Add request and response body limits for driver HTTP paths, including decompression. |
| 31 | + - The Node driver currently buffers request/response bodies and decompresses gzip/deflate without explicit caps. |
| 32 | + - Files: `packages/secure-exec/src/node/driver.ts` |
70 | 33 |
|
71 | | -- [x] Bridge `crypto.getRandomValues` / `randomUUID` to host `node:crypto` instead of `Math.random()`. |
72 | | - - Fix: runtime now wires host `node:crypto` references from `packages/secure-exec/src/index.ts` into the isolate and uses them in `packages/secure-exec/src/bridge/process.ts`. |
73 | | - - Fail-closed contract: bridge throws deterministic `crypto.getRandomValues is not supported in sandbox` / `crypto.randomUUID is not supported in sandbox` errors when host entropy hooks are unavailable. |
| 34 | +- [ ] Fix HTTP server lifecycle leaks when executions time out or are disposed. |
| 35 | + - Sandbox-owned servers need deterministic teardown on all execution shutdown paths. |
| 36 | + - Files: `packages/secure-exec/src/execution.ts`, `packages/secure-exec/src/node/execution-driver.ts`, `packages/secure-exec/src/node/driver.ts` |
74 | 37 |
|
75 | | -- [ ] Add transfer size limits on base64 file I/O across the isolate boundary. |
76 | | - - `packages/secure-exec/src/index.ts` (~line 1138, `readFileBinaryRef` / `writeFileBinaryRef`) |
77 | | - - No cap currently; a large file read can OOM the host process. |
| 38 | +- [ ] Verify timer and event-rate controls under hostile workloads. |
| 39 | + - Add explicit stress coverage for `setInterval`, `setImmediate`, and high-frequency event emission so abuse resistance is tested instead of assumed. |
| 40 | + - Files: `tests/test-suite/node/`, `tests/runtime-driver/` |
78 | 41 |
|
79 | | -- [ ] Validate size before host-side `JSON.parse` calls. |
80 | | - - `packages/secure-exec/src/index.ts` (10 unvalidated `JSON.parse` calls) |
81 | | - - Crafted large payloads from sandbox can OOM the host process. |
| 42 | +- [ ] Document extension attack vectors and hardening guidance. |
| 43 | + - Consolidate memory amplification, CPU amplification, timer/event amplification, and extension host-hook abuse paths in the internal threat model. |
| 44 | + - Files: `docs-internal/attack-vectors.md` |
82 | 45 |
|
83 | | -- [x] Make bridge globals non-writable on `globalThis`. |
84 | | - - Fix: active-handle lifecycle globals now install via `Object.defineProperty` with `writable: false` and `configurable: false`, preventing sandbox overwrite of `_registerHandle` / `_unregisterHandle` / `_waitForActiveHandles`. |
85 | | - - `packages/secure-exec/src/bridge/active-handles.ts`, `packages/secure-exec/tests/index.test.ts` |
| 46 | +## Priority 1: Compatibility and API Coverage |
86 | 47 |
|
87 | | -- [ ] Remove default host-side console buffering; drop logs by default and expose optional streaming hook. |
88 | | - - `packages/secure-exec/src/index.ts`, `packages/secure-exec/src/execution.ts` |
| 48 | +- [ ] Fix `v8.serialize` and `v8.deserialize` to use V8 structured serialization semantics. |
| 49 | + - The current JSON-based behavior is observably wrong for `Map`, `Set`, `RegExp`, circular references, and other structured-clone cases. |
| 50 | + - Files: `packages/secure-exec/isolate-runtime/src/inject/bridge-initial-globals.ts` |
89 | 51 |
|
90 | | -- [ ] Add global host resource budgets (output bytes, bridge-call rate, timer count, child-process count). |
91 | | - - `packages/secure-exec/src/index.ts`, `packages/secure-exec/src/bridge/process.ts`, `packages/secure-exec/src/shared/permissions.ts` |
| 52 | +- [ ] Add missing `fs` APIs needed for broader Node parity. |
| 53 | + - Missing APIs: `cp`, `cpSync`, `glob`, `globSync`, `opendir`, `mkdtemp`, `mkdtempSync`, `statfs`, `statfsSync`, `readv`, `readvSync`, `fdatasync`, `fdatasyncSync`, `fsync`, `fsyncSync`. |
| 54 | + - Files: `packages/secure-exec/src/bridge/fs.ts` |
92 | 55 |
|
93 | | -- [ ] Cap and hard-fail child-process output buffering in sync APIs. |
94 | | - - `packages/secure-exec/src/index.ts` (`spawnSyncRef` / `execSyncRef`) |
| 56 | +- [ ] Implement deferred `fs` APIs or explicitly keep them out of scope with stronger compatibility guidance. |
| 57 | + - Deferred APIs: `chmod`, `chown`, `link`, `symlink`, `readlink`, `truncate`, `utimes`, `watch`, `watchFile`. |
| 58 | + - Files: `packages/secure-exec/src/bridge/fs.ts`, `docs/node-compatability.mdx` |
95 | 59 |
|
96 | | -- [ ] Ensure child-process sessions are always cleaned up on timeout/dispose/error paths. |
97 | | - - `packages/secure-exec/src/index.ts` (`sessions` map in child-process bridge) |
| 60 | +- [ ] Add missing lower-level `http` and `https` APIs. |
| 61 | + - Remaining gaps include `Agent` pooling/keep-alive controls, upgrade handling, trailer headers, and socket-level events. |
| 62 | + - Files: `packages/secure-exec/src/bridge/network.ts`, `packages/secure-exec/src/node/driver.ts` |
98 | 63 |
|
99 | | -- [ ] Add request/response body limits for driver HTTP paths (including decompression). |
100 | | - - `packages/secure-exec/src/node/driver.ts` (`httpServerListen`, `fetch`, `httpRequest`) |
101 | | - |
102 | | -- [ ] Fix HTTP server lifecycle leaks when executions time out or are disposed. |
103 | | - - `packages/secure-exec/src/execution.ts`, `packages/secure-exec/src/index.ts`, `packages/secure-exec/src/node/driver.ts` |
| 64 | +- [ ] Add a dedicated lazy dynamic-import regression test. |
| 65 | + - Top-level-await plus `import()` ordering still has a tracked edge case and needs explicit coverage. |
| 66 | + - Files: `packages/secure-exec/tests/` |
104 | 67 |
|
105 | | -## API Coverage Gaps |
| 68 | +- [ ] Document and verify package-manager support for `node_modules` loading behavior. |
| 69 | + - Add compatibility fixtures that exercise npm, pnpm, yarn, and bun layouts without sandbox-aware fixture code. |
| 70 | + - Files: `packages/secure-exec/tests/projects/`, `docs/node-compatability.mdx` |
106 | 71 |
|
107 | | -- [ ] Add missing `fs` APIs: `cp`, `cpSync`, `glob`, `globSync`, `opendir`, `mkdtemp`, `mkdtempSync`, `statfs`, `statfsSync`, `readv`, `readvSync`, `fdatasync`, `fdatasyncSync`, `fsync`, `fsyncSync`. |
108 | | - - `packages/secure-exec/src/bridge/fs.ts` |
109 | | - - Goal: full `node:fs` coverage for core file operations. |
| 72 | +## Priority 2: Maintainability and Performance |
110 | 73 |
|
111 | | -- [ ] Implement deferred `fs` APIs: `chmod`, `chown`, `link`, `symlink`, `readlink`, `truncate`, `utimes`, `watch`, `watchFile`. |
112 | | - - `packages/secure-exec/src/bridge/fs.ts` |
113 | | - - Currently throw deterministic unsupported errors. |
| 74 | +- [ ] Remove remaining `@ts-nocheck` bypasses in bridge internals. |
| 75 | + - Current bypasses remain in `bridge/polyfills.ts`, `bridge/os.ts`, `bridge/child-process.ts`, `bridge/process.ts`, and `bridge/network.ts`. |
| 76 | + - Files: `packages/secure-exec/src/bridge/*.ts` |
114 | 77 |
|
115 | | -- [ ] Add missing `http`/`https` APIs: connection pooling (`Agent`), keep-alive tuning, WebSocket upgrade, trailer headers, socket-level events. |
116 | | - - `packages/secure-exec/src/bridge/network.ts` |
117 | | - - Current implementation is fetch-based and fully buffered with no socket-level control. |
| 78 | +- [ ] Split `NodeExecutionDriver` into focused modules. |
| 79 | + - The old `index.ts` monolith has moved; the main concentration of complexity is now `packages/secure-exec/src/node/execution-driver.ts`. |
| 80 | + - Suggested extraction targets: isolate bootstrap, module resolution, ESM compilation, bridge setup, and execution lifecycle. |
118 | 81 |
|
119 | | -- [ ] Fix `v8.serialize`/`v8.deserialize` to use V8 structured serialization instead of `JSON.stringify`/`JSON.parse`. |
120 | | - - `packages/secure-exec/isolate-runtime/src/inject/bridge-initial-globals.ts` (~line 51) |
121 | | - - Bug: current implementation silently produces JSON instead of V8 binary format. Code depending on structured clone semantics (`Map`, `Set`, `RegExp`, circular refs) will get wrong results. |
| 82 | +- [ ] Make ESM module reverse lookup O(1). |
| 83 | + - Large import graphs still risk quadratic resolver work. |
| 84 | + - Files: `packages/secure-exec/src/node/execution-driver.ts` |
122 | 85 |
|
123 | | -## Performance & Correctness |
| 86 | +- [ ] Add resolver memoization for positive and negative lookups. |
| 87 | + - Avoid repeated miss probes across `require()` and `import()` paths. |
| 88 | + - Files: `packages/secure-exec/src/package-bundler.ts`, `packages/secure-exec/src/shared/require-setup.ts`, `packages/secure-exec/src/node/execution-driver.ts` |
124 | 89 |
|
125 | | -- [ ] Add `stat` and `exists` methods to `VirtualFileSystem` interface. |
126 | | - - `packages/secure-exec/src/types.ts`, `packages/secure-exec/src/fs-helpers.ts` |
127 | | - - Current `stat()` and `exists()` read entire file contents; O(file size) when should be O(1). Also a DoS vector via large files. |
| 90 | +- [ ] Cap and cache `package.json` parsing in resolver paths. |
| 91 | + - Prevent repeated large-file reads and large JSON parse overhead in package resolution. |
| 92 | + - Files: `packages/secure-exec/src/package-bundler.ts` |
128 | 93 |
|
129 | | -- [ ] Split `index.ts` into focused modules. |
130 | | - - `packages/secure-exec/src/index.ts` (1,956 lines and growing) |
131 | | - - Extract: `isolate.ts`, `module-resolver.ts`, `esm-compiler.ts`, `bridge-setup.ts`, `execution.ts`. |
| 94 | +- [ ] Reduce module-access lookup overhead. |
| 95 | + - Add prefix indexing and canonicalization memoization in module-access checks. |
| 96 | + - Files: `packages/secure-exec/src/node/module-access.ts` |
132 | 97 |
|
133 | | -- [ ] Replace magic O_* flag numbers with named constants. |
134 | | - - `packages/secure-exec/src/bridge/fs.ts` (~line 690) |
135 | | - - Hardcoded integers (577, 578, 1089, etc.) are Linux-specific and undocumented. |
| 98 | +- [ ] Replace whole-file fd sync emulation with offset-based host read/write primitives. |
| 99 | + - The current approach does more work than necessary and increases large-file pressure. |
| 100 | + - Files: `packages/secure-exec/src/bridge/fs.ts` |
136 | 101 |
|
137 | | -- [ ] Fix `readDirWithTypes` N+1 I/O pattern. |
138 | | - - `packages/secure-exec/src/fs-helpers.ts` (~line 112) |
139 | | - - Calls `readDir` per entry to check if directory; add `readDirWithTypes` or `stat` to `VirtualFileSystem`. |
| 102 | +- [ ] Replace magic `O_*` flag numbers with named constants. |
| 103 | + - Hardcoded flag values are difficult to audit and easy to misuse. |
| 104 | + - Files: `packages/secure-exec/src/bridge/fs.ts` |
140 | 105 |
|
141 | | -- [ ] Make `rename` atomic or document limitation. |
142 | | - - `packages/secure-exec/src/fs-helpers.ts` (lines 90-92) |
143 | | - - Currently read + write + delete; crash between steps can duplicate or lose data. |
| 106 | +- [ ] Convert IO handling into a shared abstraction reusable across runtimes. |
| 107 | + - Shared request/response/stream/error contracts should reduce Node/browser/runtime drift. |
| 108 | + - Files: `packages/secure-exec/src/`, `tests/test-suite/` |
144 | 109 |
|
145 | | -- [ ] Make ESM module reverse-lookup O(1) to avoid O(n^2) resolver work on large import graphs. |
146 | | - - `packages/secure-exec/src/index.ts` (ESM resolver / module cache lookup) |
| 110 | +## Priority 3: Examples, Validation Breadth, and Product Direction |
147 | 111 |
|
148 | | -- [ ] Add resolver memoization (positive + negative) to avoid repeated miss probes across `require()`/`import()`. |
149 | | - - `packages/secure-exec/src/package-bundler.ts`, `packages/secure-exec/src/shared/require-setup.ts`, `packages/secure-exec/src/index.ts` |
| 112 | +- [ ] Review the Node driver against the intended long-term runtime contract. |
| 113 | + - Use the current architecture docs and glossary terms to decide what stays driver-owned versus runtime-owned. |
| 114 | + - Files: `docs-internal/arch/overview.md`, `docs-internal/glossary.md`, `packages/secure-exec/src/node/` |
150 | 115 |
|
151 | | -- [ ] Document and verify package manager support for `node_modules` loading behavior. |
152 | | - - Cover expected resolver behavior and known caveats for npm, pnpm, yarn, and bun installs. |
153 | | - - Add/maintain compatibility fixtures that exercise transitive dependency loading across supported package manager layouts. |
| 116 | +- [ ] Define the minimal driver surface needed for Rivet integration. |
| 117 | + - This should turn the high-level “minimal driver” idea into a concrete API checklist. |
| 118 | + - Files: `docs-internal/arch/overview.md`, `packages/secure-exec/src/types.ts` |
154 | 119 |
|
155 | | -- [ ] Cap and cache `package.json` parsing in resolver paths. |
156 | | - - `packages/secure-exec/src/package-bundler.ts` |
| 120 | +- [ ] Add a codemode example. |
| 121 | + - Provide a focused example that demonstrates secure-exec usage in a realistic tool flow. |
| 122 | + - Files: `examples/` |
157 | 123 |
|
158 | | -- [ ] Reduce module-access lookup overhead (prefix index + canonicalization memoization). |
159 | | - - `packages/secure-exec/src/node/module-access.ts` |
| 124 | +- [ ] Add a just-bash example. |
| 125 | + - Show the smallest useful command-execution integration without broader framework scaffolding. |
| 126 | + - Files: `examples/` |
160 | 127 |
|
161 | | -- [ ] Replace whole-file fd sync emulation with offset-based host read/write primitives. |
162 | | - - `packages/secure-exec/src/bridge/fs.ts` |
| 128 | +- [ ] Expand framework and environment validation. |
| 129 | + - Add or maintain black-box coverage for projects using Pi, Express, Hono, and other representative package stacks. |
| 130 | + - Files: `packages/secure-exec/tests/projects/` |
0 commit comments