Skill Tracer
Skills › gstack › browse › platform.ts

platform.ts

38 lines · browse/src/platform.ts at 3f79d81

1/**
2 * Cross-platform constants for gstack browse.
3 *
4 * On macOS/Linux: TEMP_DIR = '/tmp', path.sep = '/' — identical to hardcoded values.
5 * On Windows: TEMP_DIR = os.tmpdir(), path.sep = '\\' — correct Windows behavior.
6 */
7
8import * as os from 'os';
9import * as path from 'path';
11export const IS_WINDOWS = process.platform === 'win32';
12export const TEMP_DIR = IS_WINDOWS ? os.tmpdir() : '/tmp';
14/**
15 * All temp roots local commands may read/write. On macOS os.tmpdir() is the
16 * per-user /var/folders/... dir (not /tmp), and TMPDIR-honoring environments
17 * (CI, syscall-supervised sandboxes that screen /tmp) point os.tmpdir()
18 * elsewhere entirely — both are legitimate scratch space alongside the
19 * classic /tmp. Remote file serving (TEMP_ONLY in path-security.ts) stays
20 * pinned to TEMP_DIR alone; this wider set is for LOCAL path validation only.
21 */
22/** A TMPDIR pointed at `/`, the user's home, or a parent of the daemon's cwd
23 * would widen local path validation to that whole subtree for the daemon's
24 * lifetime — treat such a value as misconfiguration and ignore it. */
25function trustableTmpdir(dir: string): boolean {
26 const resolved = path.resolve(dir);
27 const home = os.homedir();
28 if (resolved === path.parse(resolved).root) return false;
29 if (resolved === home) return false;
30 return !isPathWithin(path.resolve(process.cwd()), resolved) || isPathWithin(resolved, TEMP_DIR);
33export const TEMP_DIRS = [...new Set([TEMP_DIR, os.tmpdir()].filter((d, i) => i === 0 || trustableTmpdir(d)))];
35/** Check if resolvedPath is within dir, using platform-aware separators. */
36export function isPathWithin(resolvedPath: string, dir: string): boolean {
37 return resolvedPath === dir || resolvedPath.startsWith(dir + path.sep);