test: isolate provider-home env vars so developer shells cannot leak sessions

HERMES_HOME and eight sibling PROVIDER_ENV_VARS data-dir overrides were
fingerprinted for cache invalidation but never CLEARED by the vitest
setup file, so a Hermes-shell laptop parsed real sessions in fixtures.
A static guard fails closed when the map grows another undeclared home.
This commit is contained in:
Aditya Vikram Singh 2026-08-21 18:45:15 +05:30
parent f0c6e58008
commit f55f98726d
2 changed files with 56 additions and 4 deletions

View file

@ -0,0 +1,41 @@
// Static guard: every PROVIDER_ENV_VARS entry must be CLEARED or REDIRECTED
// by tests/setup/env-isolation.ts. A data-dir override that is fingerprinted
// for cache invalidation but not isolated in tests leaks the developer's real
// sessions into fixture parses — green on CI (no HERMES_HOME), red on a
// Hermes-shell laptop. The named hole was HERMES_HOME; the class is every
// sibling override that session-cache already knows about.
import { describe, expect, it } from 'vitest'
import { readFileSync } from 'fs'
import { dirname, join } from 'path'
import { fileURLToPath } from 'url'
import { PROVIDER_ENV_VARS } from '../src/session-cache.js'
const SETUP_PATH = join(dirname(fileURLToPath(import.meta.url)), 'setup', 'env-isolation.ts')
function extractConstStringArray(source: string, name: string): string[] {
const match = source.match(new RegExp(`const ${name} = \\[([\\s\\S]*?)\\] as const`))
if (!match) {
throw new Error(`tests/setup/env-isolation.ts: const ${name} = [...] as const not found`)
}
return [...match[1]!.matchAll(/'([A-Z0-9_]+)'/g)].map(m => m[1]!)
}
describe('env-isolation covers PROVIDER_ENV_VARS', () => {
it('clears or redirects every provider data-dir override so a developer shell cannot leak real sessions into fixtures', () => {
const source = readFileSync(SETUP_PATH, 'utf8')
const isolated = new Set([
...extractConstStringArray(source, 'CLEARED'),
...extractConstStringArray(source, 'REDIRECTED'),
])
const missing: string[] = []
for (const [provider, vars] of Object.entries(PROVIDER_ENV_VARS)) {
for (const varName of vars) {
if (!isolated.has(varName)) missing.push(`${provider}:${varName}`)
}
}
expect(missing).toEqual([])
})
})

View file

@ -1,12 +1,13 @@
// Vitest setup file: isolates every test from the developer's shell environment.
//
// codeburn discovers sessions through a long list of provider-specific env
// vars (CLAUDE_CONFIG_DIR, CODEX_HOME, CRUSH_GLOBAL_DATA, …) and via HOME /
// XDG_* / APPDATA / LOCALAPPDATA. Without this file, any value set in the
// developer's shell (e.g. CLAUDE_CONFIG_DIRS=/Users/me/.claude:…) bleeds into
// vars (CLAUDE_CONFIG_DIR, CODEX_HOME, HERMES_HOME, CRUSH_GLOBAL_DATA, …) and
// via HOME / XDG_* / APPDATA / LOCALAPPDATA. Without this file, any value set
// in the developer's shell (e.g. HERMES_HOME=/Users/me/.hermes) bleeds into
// fixture-based tests: the parser reads the developer's REAL sessions instead
// of the temp-dir fixture, producing nonsense totals and false failures that
// pass on a clean CI runner.
// pass on a clean CI runner. tests/env-isolation-declarations.test.ts fails
// closed if PROVIDER_ENV_VARS grows a data-dir override that is not listed.
//
// What this file does:
// 1. Mints an empty sandbox temp dir once per worker.
@ -56,26 +57,36 @@ const CLEARED = [
'CODEWHALE_HOME',
'CRUSH_GLOBAL_DATA',
'CODEBUFF_DATA_DIR',
'DSH_HOME',
'FACTORY_DIR',
'GOOSE_PATH_ROOT',
'GROK_HOME',
'HERMES_HOME',
'KIRO_HOME',
'KIMI_CODE_HOME',
'KIMI_SHARE_DIR',
'LINGTAI_HOME',
'LINGTAI_TUI_GLOBAL_DIR',
'LINGTAI_TUI_HOME',
'MUX_ROOT',
'OPENCODE_DATA_DIR',
'OPENCODE_DB_PREFIX',
'QUICKWORK_HOME',
'QWEN_DATA_DIR',
'VIBE_HOME',
'WARP_DB_PATH',
'ZS_DATA_DIR',
// codeburn override dirs / paths
'CODEBURN_CACHE_DIR',
'CODEBURN_COPILOT_GLOBAL_STORAGE_DIR',
'CODEBURN_COPILOT_JETBRAINS_DIR',
'CODEBURN_COPILOT_OTEL_DB',
'CODEBURN_COPILOT_SESSION_STATE_DIR',
'CODEBURN_COPILOT_WS_STORAGE_DIR',
'CODEBURN_DESKTOP_SESSIONS_DIR',
'CODEBURN_MUX_DIR',
'CODEBURN_OPEN_DESIGN_DIR',
'CODEBURN_OPENCLAUDE_DIR',
'CODEBURN_ANTIGRAVITY_SETTINGS_PATH',
// codeburn behavior toggles (set by the dev to tweak local runs)
'CODEBURN_COPILOT_DISABLE_OTEL',