Skip to content

Commit ecea657

Browse files
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
1 parent 9e3fa3e commit ecea657

2 files changed

Lines changed: 73 additions & 1 deletion

File tree

‎apps/server/src/terminalManager.test.ts‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,4 +424,49 @@ describe("TerminalManager", () => {
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‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ import { runProcess } from "./processRunner";
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 {
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> {
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> {
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;

0 commit comments

Comments
 (0)