/** * JIT layer-2 tools — permission guards (R1 pipeline). * * P2 (path level, tm_read / tm_grep scope): read scope = project root + * blackboard dir + trajectory dir. Everything else — including `..` escapes * and absolute paths outside the scopes — is rejected. Both the target and * each scope are fs.realpathSync'd first (fail-closed): a junction/symlink * pointing outside the scope defeats purely lexical resolve/relative checks. * * P3 (command level, tm_bash): a read-only allowlist gates what R6 does not * already forbid. The two layers are deliberately non-conflicting: * R6 governs what is FORBIDDEN (env dumps, env files — same source); * the P3 allowlist governs what is PERMITTED (read-only heads only). * Hardening beyond the head token: output redirection, command substitution * ($()/backticks/<>()), VAR=value assignment prefixes (BASH_ENV/LD_PRELOAD/ * PATH borrow an allowlisted head to run arbitrary scripts — fail closed), * find -delete/-exec, tail -f and Get-Content/Get-ChildItem -Wait (hang), * awk system() and rg --pre are rejected even under allowlisted heads. * Quoted metacharacters (`|`, `;`, `>`, single-quoted `$()`) are literal * text in both dialects — one shared quote-blanking view keeps segmentation * and the redirect/substitution checks from misreading them (see the * blankQuoted helpers; one implementation, never two drifting copies). */ export interface AllowVerdict { ok: boolean; reason?: string; suggestion?: string; } /** * Classify a tm_bash command against the read-only allowlist. * Every segment head (across && ; | & and newlines) must be allowlisted. * Matching is case-insensitive (PowerShell is; sh spellings are unaffected). */ export declare function classifyReadonlyCommand(command: string, allowlist: readonly string[]): AllowVerdict; /** True when `target` resolves inside `rootDir` (win32 compares case-insensitively). */ export declare function isInsideDir(rootDir: string, target: string): boolean; export type PathScopeVerdict = { ok: true; abs: string; } | { ok: false; message: string; }; /** * Resolve a requested path against the tool's directory and enforce the P2 * read scope (project root + extra dirs, i.e. blackboard + trajectory). * Junction/symlink hardening (#6): BOTH the target and each scope dir are * fs.realpathSync'd before the containment check — a purely lexical * resolve/relative is defeated by a junction pointing outside the scope. * Fail-closed: an unresolvable target is rejected; a scope dir that cannot * be resolved (not created yet) simply cannot contain anything real and is * skipped. The error message never echoes env-file style paths beyond the * scope verdict itself (R6 rejections upstream carry no path text at all). */ export declare function assertReadablePath(baseDir: string, requested: unknown, extraDirs?: readonly string[]): PathScopeVerdict; //# sourceMappingURL=guard.d.ts.map