History

Filter app runtime env vars from terminal spawn environment

- build terminal spawn env from a filtered copy of process env - exclude `PORT`, `T3CODE_*`, `VITE_*`, and Electron runtime vars - add test coverage to verify filtered and preserved env keys

Julius Marminge committed 9 months ago

Commit ecea6571 parent 9e3fa3e2 files · +73 −1Browse files

Unified · Split

2 files
  1. apps/server/src/terminalManager.test.ts +45 −0
  2. apps/server/src/terminalManager.ts +28 −1
apps/server/src/terminalManager.test.ts+45−0
@@ -424,4 +424,49 @@ describe("TerminalManager", () => { · 423 unmodified lines
424424
425425 manager.dispose();
426426 });
427+
428+ it("filters app runtime env variables from terminal sessions", async () => {
429+ const originalValues = new Map<string, string | undefined>();
430+ const setEnv = (key: string, value: string | undefined) => {
431+ if (!originalValues.has(key)) {
432+ originalValues.set(key, process.env[key]);
433+ }
434+ if (value === undefined) {
435+ delete process.env[key];
436+ return;
437+ }
438+ process.env[key] = value;
439+ };
440+ const restoreEnv = () => {
441+ for (const [key, value] of originalValues) {
442+ if (value === undefined) {
443+ delete process.env[key];
444+ } else {
445+ process.env[key] = value;
446+ }
447+ }
448+ };
449+
450+ setEnv("PORT", "5173");
451+ setEnv("T3CODE_PORT", "3773");
452+ setEnv("VITE_DEV_SERVER_URL", "http://localhost:5173");
453+ setEnv("TEST_TERMINAL_KEEP", "keep-me");
454+
455+ try {
456+ const { manager, ptyAdapter } = makeManager();
457+ await manager.open(openInput());
458+ const spawnInput = ptyAdapter.spawnInputs[0];
459+ expect(spawnInput).toBeDefined();
460+ if (!spawnInput) return;
461+
462+ expect(spawnInput.env.PORT).toBeUndefined();
463+ expect(spawnInput.env.T3CODE_PORT).toBeUndefined();
464+ expect(spawnInput.env.VITE_DEV_SERVER_URL).toBeUndefined();
465+ expect(spawnInput.env.TEST_TERMINAL_KEEP).toBe("keep-me");
466+
467+ manager.dispose();
468+ } finally {
469+ restoreEnv();
470+ }
471+ });
427472 });
apps/server/src/terminalManager.ts+28−1
@@ -26,6 +26,11 @@ import { runProcess } from "./processRunner"; · 25 unmodified lines
2626 const DEFAULT_HISTORY_LINE_LIMIT = 5_000;
2727 const DEFAULT_PERSIST_DEBOUNCE_MS = 40;
2828 const DEFAULT_SUBPROCESS_POLL_INTERVAL_MS = 1_000;
29+const TERMINAL_ENV_BLOCKLIST = new Set([
30+ "PORT",
31+ "ELECTRON_RENDERER_PORT",
32+ "ELECTRON_RUN_AS_NODE",
33+]);
2934
3035 type TerminalSubprocessChecker = (terminalPid: number) => Promise<boolean>;
3136
@@ -234,6 +239,27 @@ function toSessionKey(threadId: string, terminalId: string): string { · 202 unmodified lines
234239 return `${threadId}\u0000${terminalId}`;
235240 }
236241
242+function shouldExcludeTerminalEnvKey(key: string): boolean {
243+ const normalizedKey = key.toUpperCase();
244+ if (normalizedKey.startsWith("T3CODE_")) {
245+ return true;
246+ }
247+ if (normalizedKey.startsWith("VITE_")) {
248+ return true;
249+ }
250+ return TERMINAL_ENV_BLOCKLIST.has(normalizedKey);
251+}
252+
253+function createTerminalSpawnEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
254+ const spawnEnv: NodeJS.ProcessEnv = {};
255+ for (const [key, value] of Object.entries(baseEnv)) {
256+ if (value === undefined) continue;
257+ if (shouldExcludeTerminalEnvKey(key)) continue;
258+ spawnEnv[key] = value;
259+ }
260+ return spawnEnv;
261+}
262+
237263 export class TerminalManager extends EventEmitter<TerminalManagerEvents> {
238264 private readonly sessions = new Map<string, TerminalSessionState>();
239265 private readonly logsDir: string;
@@ -467,6 +493,7 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { · 227 unmodified lines
467493 let startedShell: string | null = null;
468494 try {
469495 const shellCandidates = resolveShellCandidates(this.shellResolver);
496+ const terminalEnv = createTerminalSpawnEnv(process.env);
470497 let lastSpawnError: unknown = null;
471498
472499 for (const shell of shellCandidates) {
@@ -476,7 +503,7 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { · 3 unmodified lines
476503 cwd: session.cwd,
477504 cols: session.cols,
478505 rows: session.rows,
479− env: process.env,
506+ env: terminalEnv,
480507 });
481508 startedShell = shell;
482509 break;