@@ -14,40 +14,9 @@ import {
1414 type SpawnOptionsWithoutStdio ,
1515} from 'node:child_process' ;
1616
17- /**
18- * The exact HUP-signal guard preamble injected by ensureHupIgnored().
19- * Exported so shellExecutionService and stripShellWrapper stay in sync.
20- */
21- export const BASH_HUP_GUARD = `trap '' HUP;` ;
22-
23- /**
24- * Strips the SIGHUP guard prepended by ensureHupIgnored() from a command.
25- *
26- * This is intentionally narrow: it only removes the exact literal string
27- * `trap '' HUP; ` from the very start of a command. It does NOT
28- * skip or ignore arbitrary user-supplied `trap` commands, which would be a
29- * sandbox-bypass vector (e.g., `trap 'rm -rf /' EXIT; git status`).
30- */
31- export function stripHupGuard ( command : string ) : string {
32- const trimmed = command . trimStart ( ) ;
33- const prefix = `${ BASH_HUP_GUARD } ` ;
34- if ( trimmed . startsWith ( prefix ) ) {
35- return trimmed . slice ( prefix . length ) ;
36- }
37- // Handle case where there's no trailing space (e.g., guard is the whole command)
38- if ( trimmed === BASH_HUP_GUARD ) {
39- return '' ;
40- }
41- return command ;
42- }
43-
4417/**
4518 * Extracts the primary command name from a potentially wrapped shell command.
46- * Strips shell wrappers (including our own HUP guard) and handles shopt/set/etc.
47- *
48- * Returns the command name only when there is exactly ONE non-builtin root so
49- * that chained commands (e.g. `git; malicious_cmd`) never silently inherit the
50- * first command's sandbox permissions.
19+ * Strips shell wrappers and handles shopt/set/etc.
5120 *
5221 * @param command - The full command string.
5322 * @param args - The arguments for the command.
@@ -63,10 +32,7 @@ export async function getCommandName(
6332 const roots = getCommandRoots ( stripped ) . filter (
6433 ( r ) => r !== 'shopt' && r !== 'set' ,
6534 ) ;
66- // Single-root enforcement: only grant named-command permissions when the
67- // command is unambiguous. Multi-root chains fall back to basename so that
68- // `git; malicious_cmd` never inherits `git`'s sandbox policy.
69- if ( roots . length === 1 ) {
35+ if ( roots . length > 0 ) {
7036 return roots [ 0 ] ;
7137 }
7238 return path . basename ( command ) ;
@@ -877,7 +843,6 @@ export function stripShellWrapper(command: string): string {
877843 const pattern =
878844 / ^ \s * (?: (?: (?: \S + \/ ) ? (?: s h | b a s h | z s h ) ) \s + - c | c m d \. e x e \s + \/ c | p o w e r s h e l l (?: \. e x e ) ? \s + (?: - N o P r o f i l e \s + ) ? - C o m m a n d | p w s h (?: \. e x e ) ? \s + (?: - N o P r o f i l e \s + ) ? - C o m m a n d ) \s + / i;
879845 const match = command . match ( pattern ) ;
880- let result : string ;
881846 if ( match ) {
882847 let newCommand = command . substring ( match [ 0 ] . length ) . trim ( ) ;
883848 if (
@@ -886,13 +851,9 @@ export function stripShellWrapper(command: string): string {
886851 ) {
887852 newCommand = newCommand . substring ( 1 , newCommand . length - 1 ) ;
888853 }
889- result = newCommand ;
890- } else {
891- result = command . trim ( ) ;
854+ return newCommand ;
892855 }
893- // Peel off the SIGHUP guard that ensureHupIgnored() prepends so that
894- // sandbox managers see the actual user command, not our preamble.
895- return stripHupGuard ( result ) ;
856+ return command . trim ( ) ;
896857}
897858
898859/**
0 commit comments