Files
gstack/browse/src/platform.ts
T
Garry TanandClaude Fable 5 97d33a90ad fix(browse): portable temp paths — TEMP_DIRS allowlist, tmpdir()-based test files
Local path validation now accepts os.tmpdir() alongside the classic /tmp
(new TEMP_DIRS in platform.ts): on macOS os.tmpdir() is /var/folders/...,
and TMPDIR-honoring CI/sandbox environments point it elsewhere entirely —
both are legitimate scratch space. Remote file serving (TEMP_ONLY) stays
pinned to TEMP_DIR alone; no change to the exfil boundary.

commands.test.ts drops 41 hardcoded /tmp literals for a tmpp() helper on
os.tmpdir() (two message assertions now reference the same variable), and
path-validation's symlink-escape test targets /etc/hosts instead of
/etc/crontab — the target must EXIST for realpath to resolve the link (a
dangling target falls back to the link's own path and passes vacuously),
and /etc/crontab is absent on Amazon Linux.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 19:59:06 +00:00

28 lines
1.1 KiB
TypeScript

/**
* Cross-platform constants for gstack browse.
*
* On macOS/Linux: TEMP_DIR = '/tmp', path.sep = '/' — identical to hardcoded values.
* On Windows: TEMP_DIR = os.tmpdir(), path.sep = '\\' — correct Windows behavior.
*/
import * as os from 'os';
import * as path from 'path';
export const IS_WINDOWS = process.platform === 'win32';
export const TEMP_DIR = IS_WINDOWS ? os.tmpdir() : '/tmp';
/**
* All temp roots local commands may read/write. On macOS os.tmpdir() is the
* per-user /var/folders/... dir (not /tmp), and TMPDIR-honoring environments
* (CI, syscall-supervised sandboxes that screen /tmp) point os.tmpdir()
* elsewhere entirely — both are legitimate scratch space alongside the
* classic /tmp. Remote file serving (TEMP_ONLY in path-security.ts) stays
* pinned to TEMP_DIR alone; this wider set is for LOCAL path validation only.
*/
export const TEMP_DIRS = [...new Set([TEMP_DIR, os.tmpdir()])];
/** Check if resolvedPath is within dir, using platform-aware separators. */
export function isPathWithin(resolvedPath: string, dir: string): boolean {
return resolvedPath === dir || resolvedPath.startsWith(dir + path.sep);
}