Skip to content

fix(security): send sensitive config over a bootstrap fd#1398

Merged
juliusmarminge merged 5 commits intomainfrom
t3code/investigate-auth-token-leak
Mar 25, 2026
Merged

fix(security): send sensitive config over a bootstrap fd#1398
juliusmarminge merged 5 commits intomainfrom
t3code/investigate-auth-token-leak

Conversation

@juliusmarminge
Copy link
Member

@juliusmarminge juliusmarminge commented Mar 25, 2026

Summary

  • Add --bootstrap-fd / T3CODE_BOOTSTRAP_FD support so startup config can be delivered through an inherited file descriptor instead of env vars or command-line args.
  • Update server config resolution to merge CLI, env, and bootstrap envelope values with explicit precedence and validation.
  • Switch the desktop launcher/preload bridge to pass the auth token through the bootstrap pipe and fetch the websocket URL from main process IPC.
  • Update remote startup docs to describe the bootstrap flow and its security benefits.
  • Add coverage for bootstrap envelope parsing and config precedence behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test

Note

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

  • The desktop app now writes a one-shot JSON envelope (mode, port, auth token, etc.) to an inherited pipe on fd 3 when spawning the backend, instead of passing values via T3CODE_* environment variables.
  • apps/server/src/bootstrap.ts implements readBootstrapEnvelope, which reads a single NDJSON line from the fd, with timeout support and graceful handling of unavailable fds.
  • apps/server/src/main.ts resolves config with precedence: CLI flags > env vars > bootstrap envelope > defaults. authToken is now optional if not provided by any source.
  • The preload bridge's getWsUrl now fetches the WebSocket URL via synchronous IPC (desktop:get-ws-url) instead of reading T3CODE_DESKTOP_WS_URL from the environment.
  • Behavioral Change: backend child processes no longer inherit T3CODE_* vars from the desktop launcher; the dev:desktop dev runner also stops exporting these vars.

Macroscope summarized e7460fb.

- 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
@coderabbitai
Copy link

coderabbitai bot commented Mar 25, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f3749efa-b0bc-42ed-9463-f0a3b7cda809

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/investigate-auth-token-leak

Comment @coderabbitai help to get the list of available commands and usage tips.

@juliusmarminge juliusmarminge marked this pull request as draft March 25, 2026 08:35
@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 25, 2026
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

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.

Create PR

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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

juliusmarminge and others added 3 commits March 25, 2026 09:25
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarminge juliusmarminge changed the title Add bootstrap fd for desktop auth token fix(security): send sensitive config over a bootstrap fd Mar 25, 2026
@juliusmarminge juliusmarminge marked this pull request as ready for review March 25, 2026 16:44
@juliusmarminge juliusmarminge merged commit b3bca04 into main Mar 25, 2026
14 checks passed
@juliusmarminge juliusmarminge deleted the t3code/investigate-auth-token-leak branch March 25, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants