mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-16 09:55:29 +02:00
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>
This commit is contained in:
co-authored by
Claude Fable 5
parent
626ebc1ba9
commit
97d33a90ad
@@ -12,16 +12,18 @@
|
||||
* Security invariants:
|
||||
* 1. All paths resolved to absolute before checking
|
||||
* 2. Symlinks resolved to catch traversal via symlink inside safe dir
|
||||
* 3. SAFE_DIRECTORIES = [TEMP_DIR, cwd] for local commands
|
||||
* 3. SAFE_DIRECTORIES = [...TEMP_DIRS, cwd] for local commands (TEMP_DIRS =
|
||||
* classic TEMP_DIR plus os.tmpdir(), which differ on macOS and under
|
||||
* TMPDIR-honoring CI/sandbox environments)
|
||||
* 4. TEMP_ONLY = [TEMP_DIR] for remote file serving (prevents project file exfil)
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { TEMP_DIR, isPathWithin } from './platform';
|
||||
import { TEMP_DIR, TEMP_DIRS, isPathWithin } from './platform';
|
||||
|
||||
// Resolve safe directories through realpathSync to handle symlinks (e.g., macOS /tmp → /private/tmp)
|
||||
export const SAFE_DIRECTORIES = [TEMP_DIR, process.cwd()].map(d => {
|
||||
export const SAFE_DIRECTORIES = [...TEMP_DIRS, process.cwd()].map(d => {
|
||||
try { return fs.realpathSync(d); } catch { return d; }
|
||||
});
|
||||
|
||||
|
||||
@@ -11,6 +11,16 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user