fix(security): send sensitive config over a bootstrap fd#1398
fix(security): send sensitive config over a bootstrap fd#1398juliusmarminge merged 5 commits intomainfrom
Conversation
- Pass one-shot startup config over inherited fd instead of env - Wire server bootstrap parsing and desktop IPC for websocket URL - Add tests for bootstrap envelope precedence and timeout handling
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Inherited env vars silently override bootstrap envelope config
- Explicitly cleared T3CODE_MODE, T3CODE_PORT, T3CODE_HOME, T3CODE_NO_BROWSER, and T3CODE_AUTH_TOKEN from the child process env in the desktop launcher so stray inherited env vars cannot override the bootstrap pipe values.
- ✅ Fixed: Bootstrap fd path resolution fails on Windows
- Made resolveFdPath return undefined on win32 and updated readBootstrapEnvelope to use the raw fd number directly when no virtual fd path is available, allowing Node's fs APIs to read the inherited pipe handle natively.
Or push these changes by commenting:
@cursor push 06b5fc27b5
Preview (06b5fc27b5)
diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts
--- a/apps/desktop/src/main.ts
+++ b/apps/desktop/src/main.ts
@@ -949,6 +949,13 @@
env: {
...process.env,
ELECTRON_RUN_AS_NODE: "1",
+ // Clear env vars that the bootstrap pipe now delivers, so stray
+ // values inherited from the user's shell cannot override them.
+ T3CODE_MODE: undefined,
+ T3CODE_PORT: undefined,
+ T3CODE_HOME: undefined,
+ T3CODE_NO_BROWSER: undefined,
+ T3CODE_AUTH_TOKEN: undefined,
},
stdio: captureBackendLogs
? ["ignore", "pipe", "pipe", "pipe"]
diff --git a/apps/server/src/bootstrap.ts b/apps/server/src/bootstrap.ts
--- a/apps/server/src/bootstrap.ts
+++ b/apps/server/src/bootstrap.ts
@@ -35,7 +35,11 @@
if (!fdReady) return Option.none();
const streamFd = yield* Effect.try({
- try: () => NFS.openSync(resolveFdPath(fd), "r"),
+ try: () => {
+ const fdPath = resolveFdPath(fd);
+ if (fdPath === undefined) return fd;
+ return NFS.openSync(fdPath, "r");
+ },
catch: (error) =>
new BootstrapError({
message: "Failed to duplicate bootstrap fd.",
@@ -113,9 +117,12 @@
);
}
-function resolveFdPath(fd: number): string {
+function resolveFdPath(fd: number): string | undefined {
if (process.platform === "linux") {
return `/proc/self/fd/${fd}`;
}
+ if (process.platform === "win32") {
+ return undefined;
+ }
return `/dev/fd/${fd}`;
}- Strip T3CODE_* bootstrap vars from the Electron child env - Add a regression test for dev:desktop env sanitization
| contextBridge.exposeInMainWorld("desktopBridge", { | ||
| getWsUrl: () => wsUrl, | ||
| getWsUrl: () => { | ||
| const result = ipcRenderer.sendSync(GET_WS_URL_CHANNEL); |
There was a problem hiding this comment.
Is there a specific reason we're using ipcRenderer.sendSync to get the WebSocket URL here? Since it blocks the renderer's main thread until the main process responds, it could cause some visible stutter or 'jank' during the app's startup sequence. It might be smoother for the user if we switch this to an async ipcRenderer.invoke call or handle it during the load process unless you have a better solution


Summary
--bootstrap-fd/T3CODE_BOOTSTRAP_FDsupport so startup config can be delivered through an inherited file descriptor instead of env vars or command-line args.Testing
bun fmtbun lintbun typecheckbun run testNote
Cursor Bugbot is generating a summary for commit 20c0564. Configure here.
Note
Send sensitive server config over a bootstrap file descriptor instead of environment variables
T3CODE_*environment variables.apps/server/src/bootstrap.tsimplementsreadBootstrapEnvelope, which reads a single NDJSON line from the fd, with timeout support and graceful handling of unavailable fds.apps/server/src/main.tsresolves config with precedence: CLI flags > env vars > bootstrap envelope > defaults.authTokenis now optional if not provided by any source.getWsUrlnow fetches the WebSocket URL via synchronous IPC (desktop:get-ws-url) instead of readingT3CODE_DESKTOP_WS_URLfrom the environment.T3CODE_*vars from the desktop launcher; thedev:desktopdev runner also stops exporting these vars.Macroscope summarized e7460fb.