diff --git a/src/container/ca.ts b/src/container/ca.ts index 0d526b9..52a0eba 100644 --- a/src/container/ca.ts +++ b/src/container/ca.ts @@ -9,12 +9,17 @@ const SYSTEM_CA_PATHS = [ "/etc/pki/tls/certs/ca-bundle.crt", // RHEL / CentOS / Fedora ]; +/** Per-user cache dir. XDG_RUNTIME_DIR is per-user on Linux; tmpdir() fallback covers macOS/Windows. */ +function caCacheDir(): string { + return process.env.XDG_RUNTIME_DIR ?? tmpdir(); +} + /** - * Write the proxy CA certificate PEM to a temp file on the host. + * Write the proxy CA certificate PEM to a per-user file on the host. * Returns the path to the written file. */ export function writeCaCertificate(caCertificate: string): string { - const outPath = join(tmpdir(), "onecli-proxy-ca.pem"); + const outPath = join(caCacheDir(), "onecli-proxy-ca.pem"); writeFileSync(outPath, caCertificate); return outPath; } @@ -28,7 +33,7 @@ export function buildCombinedCaBundle(caCertificate: string): string | null { try { const sysCa = readFileSync(sysPath, "utf8"); const combined = sysCa.trimEnd() + "\n" + caCertificate.trimEnd() + "\n"; - const outPath = join(tmpdir(), "onecli-combined-ca.pem"); + const outPath = join(caCacheDir(), "onecli-combined-ca.pem"); writeFileSync(outPath, combined); return outPath; } catch { diff --git a/test/container/ca.test.ts b/test/container/ca.test.ts index 6e5c8b5..8ef8c54 100644 --- a/test/container/ca.test.ts +++ b/test/container/ca.test.ts @@ -16,6 +16,18 @@ vi.mock("os", async (importOriginal) => { return { ...original, tmpdir: () => isolatedTmp }; }); +// The per-user-isolation fix prefers XDG_RUNTIME_DIR over tmpdir(). Point it at +// the isolated dir so cert writes are deterministic on hosts where it's set. +let savedXdgRuntimeDir: string | undefined; +beforeAll(() => { + savedXdgRuntimeDir = process.env.XDG_RUNTIME_DIR; + process.env.XDG_RUNTIME_DIR = isolatedTmp; +}); +afterAll(() => { + if (savedXdgRuntimeDir === undefined) delete process.env.XDG_RUNTIME_DIR; + else process.env.XDG_RUNTIME_DIR = savedXdgRuntimeDir; +}); + describe("writeCaCertificate", () => { it("writes PEM to tmpdir and returns path", () => { const path = writeCaCertificate(PROXY_CA); diff --git a/test/container/client.test.ts b/test/container/client.test.ts index b65f8c0..7799b87 100644 --- a/test/container/client.test.ts +++ b/test/container/client.test.ts @@ -255,7 +255,7 @@ describe("ContainerClient", () => { addHostMapping: false, }); - const expectedHostPath = join(tmpdir(), "onecli-proxy-ca.pem"); + const expectedHostPath = join(process.env.XDG_RUNTIME_DIR ?? tmpdir(), "onecli-proxy-ca.pem"); const mountArg = args.find((a) => a.includes(":") && a.includes("onecli-proxy-ca.pem") && a.endsWith(":ro")); expect(mountArg).toBe( `${expectedHostPath}:${MOCK_CONFIG.caCertificateContainerPath}:ro`,