From 23781bb1a78974c64d8fdafeefe7cc1756220b4c Mon Sep 17 00:00:00 2001 From: Arham Wani Date: Fri, 31 Jul 2026 11:40:38 +0530 Subject: [PATCH] fix(server): scrub AppImage XDG_DATA_DIRS and GSETTINGS_SCHEMA_DIR from terminals The integrated terminal inherits the server process environment. On Linux AppImage builds the runtime's `AppRun` points `XDG_DATA_DIRS` at an `$APPDIR/usr/share` entry and `GSETTINGS_SCHEMA_DIR` at the bundled `$APPDIR/usr/share/glib-2.0/schemas`. The existing scrub (added for #1699) only cleaned `PATH`/`LD_LIBRARY_PATH`, so those two leaked into the PTY and `gsettings` inside the terminal reported "No schemas installed" (and tools saw the AppImage's data dir instead of the host's). Both are colon-separated search paths, so add them to the same `APPIMAGE_PATH_LIKE_ENV_KEYS` scrub: the AppImage mount segments are dropped and the user's real entries preserved, and when only mount segments remain the variable is removed so the shell falls back to the platform default. Extended the existing AppImage terminal test to assert both. Closes #5059 Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/server/src/terminal/Manager.test.ts | 7 +++++++ apps/server/src/terminal/Manager.ts | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/server/src/terminal/Manager.test.ts b/apps/server/src/terminal/Manager.test.ts index 1cf7e8dffec..dca3573bbcf 100644 --- a/apps/server/src/terminal/Manager.test.ts +++ b/apps/server/src/terminal/Manager.test.ts @@ -1345,6 +1345,8 @@ it.layer( OWD: "/home/user/project", PATH: `${appDir}/usr/bin:${appDir}:/usr/local/bin:/usr/bin:/bin`, LD_LIBRARY_PATH: `${appDir}/usr/lib:/home/user/.local/lib`, + XDG_DATA_DIRS: `${appDir}/usr/share:/usr/local/share:/usr/share`, + GSETTINGS_SCHEMA_DIR: `${appDir}/usr/share/glib-2.0/schemas`, TEST_TERMINAL_KEEP: "keep-me", }, }); @@ -1364,6 +1366,11 @@ it.layer( // mount segments that the runtime prepended. expect(spawnInput.env.PATH).toBe("/usr/local/bin:/usr/bin:/bin"); expect(spawnInput.env.LD_LIBRARY_PATH).toBe("/home/user/.local/lib"); + // XDG_DATA_DIRS keeps the host entries but drops the AppImage share dir. + expect(spawnInput.env.XDG_DATA_DIRS).toBe("/usr/local/share:/usr/share"); + // GSETTINGS_SCHEMA_DIR pointed only at the mount, so it is removed and + // gsettings falls back to the host schema location. + expect(spawnInput.env.GSETTINGS_SCHEMA_DIR).toBeUndefined(); // Unrelated host vars still pass through untouched. expect(spawnInput.env.TEST_TERMINAL_KEEP).toBe("keep-me"); }), diff --git a/apps/server/src/terminal/Manager.ts b/apps/server/src/terminal/Manager.ts index caa5106bb9f..5ddbbfadc22 100644 --- a/apps/server/src/terminal/Manager.ts +++ b/apps/server/src/terminal/Manager.ts @@ -1069,10 +1069,19 @@ function shouldExcludeTerminalEnvKey(key: string): boolean { // They describe the AppImage itself, not the user's session, so terminals must // not inherit them. const APPIMAGE_RUNTIME_ENV_KEYS = ["APPIMAGE", "APPDIR", "ARGV0", "OWD"] as const; -// PATH-style variables the AppImage runtime prepends with its temporary mount -// (e.g. /tmp/.mount_T3-XXXX/usr/bin). Only the mount segments are dropped; the -// user's real entries are preserved. -const APPIMAGE_PATH_LIKE_ENV_KEYS = ["PATH", "LD_LIBRARY_PATH"] as const; +// Colon-separated search-path variables the AppImage runtime points at its +// temporary mount (e.g. /tmp/.mount_T3-XXXX/usr/bin, the bundled glib schemas, +// and an $APPDIR/usr/share XDG data entry). Only the mount segments are +// dropped; the user's real entries are preserved. When nothing but mount +// segments remain the variable is removed entirely so consumers fall back to +// their platform default (e.g. gsettings finds the host schemas instead of +// reporting "No schemas installed"). See issues #1699 and #5059. +const APPIMAGE_PATH_LIKE_ENV_KEYS = [ + "PATH", + "LD_LIBRARY_PATH", + "XDG_DATA_DIRS", + "GSETTINGS_SCHEMA_DIR", +] as const; function isPathSegmentUnderAppDir(segment: string, appDir: string): boolean { return segment === appDir || segment.startsWith(`${appDir}/`);