66
77import { type FunctionCall } from '@google/genai' ;
88import {
9- isDangerousCommand ,
10- isKnownSafeCommand ,
11- } from '../sandbox/macos/commandSafety.js' ;
9+ SHELL_TOOL_NAMES ,
10+ initializeShellParsers ,
11+ splitCommands ,
12+ hasRedirection ,
13+ extractStringFromParseEntry ,
14+ } from '../utils/shell-utils.js' ;
1215import { parse as shellParse } from 'shell-quote' ;
1316import {
1417 PolicyDecision ,
@@ -24,12 +27,6 @@ import { stableStringify } from './stable-stringify.js';
2427import { debugLogger } from '../utils/debugLogger.js' ;
2528import type { CheckerRunner } from '../safety/checker-runner.js' ;
2629import { SafetyCheckDecision } from '../safety/protocol.js' ;
27- import {
28- SHELL_TOOL_NAMES ,
29- initializeShellParsers ,
30- splitCommands ,
31- hasRedirection ,
32- } from '../utils/shell-utils.js' ;
3330import { getToolAliases } from '../tools/tool-names.js' ;
3431import {
3532 MCP_TOOL_PREFIX ,
@@ -38,6 +35,10 @@ import {
3835 formatMcpToolName ,
3936 isMcpToolName ,
4037} from '../tools/mcp-tool.js' ;
38+ import {
39+ type SandboxManager ,
40+ NoopSandboxManager ,
41+ } from '../services/sandboxManager.js' ;
4142
4243function isWildcardPattern ( name : string ) : boolean {
4344 return name === '*' || name . includes ( '*' ) ;
@@ -197,8 +198,7 @@ export class PolicyEngine {
197198 private readonly disableAlwaysAllow : boolean ;
198199 private readonly checkerRunner ?: CheckerRunner ;
199200 private approvalMode : ApprovalMode ;
200- private toolSandboxEnabled : boolean ;
201- private sandboxApprovedTools : string [ ] ;
201+ private readonly sandboxManager : SandboxManager ;
202202
203203 constructor ( config : PolicyEngineConfig = { } , checkerRunner ?: CheckerRunner ) {
204204 this . rules = ( config . rules ?? [ ] ) . sort (
@@ -249,18 +249,14 @@ export class PolicyEngine {
249249 this . disableAlwaysAllow = config . disableAlwaysAllow ?? false ;
250250 this . checkerRunner = checkerRunner ;
251251 this . approvalMode = config . approvalMode ?? ApprovalMode . DEFAULT ;
252- this . toolSandboxEnabled = config . toolSandboxEnabled ?? false ;
253- this . sandboxApprovedTools = config . sandboxApprovedTools ?? [ ] ;
252+ this . sandboxManager = config . sandboxManager ?? new NoopSandboxManager ( ) ;
254253 }
255254
256255 /**
257256 * Update the current approval mode.
258257 */
259- setApprovalMode ( mode : ApprovalMode , sandboxApprovedTools ?: string [ ] ) : void {
258+ setApprovalMode ( mode : ApprovalMode ) : void {
260259 this . approvalMode = mode ;
261- if ( sandboxApprovedTools !== undefined ) {
262- this . sandboxApprovedTools = sandboxApprovedTools ;
263- }
264260 }
265261
266262 /**
@@ -285,8 +281,9 @@ export class PolicyEngine {
285281 if ( ! hasRedirection ( command ) ) return false ;
286282
287283 // Do not downgrade (do not ask user) if sandboxing is enabled and in AUTO_EDIT or YOLO
284+ const sandboxEnabled = ! ( this . sandboxManager instanceof NoopSandboxManager ) ;
288285 if (
289- this . toolSandboxEnabled &&
286+ sandboxEnabled &&
290287 ( this . approvalMode === ApprovalMode . AUTO_EDIT ||
291288 this . approvalMode === ApprovalMode . YOLO )
292289 ) {
@@ -299,27 +296,24 @@ export class PolicyEngine {
299296 /**
300297 * Check if a shell command is allowed.
301298 */
302-
303299 private async applyShellHeuristics (
304300 command : string ,
305301 decision : PolicyDecision ,
306302 ) : Promise < PolicyDecision > {
307303 await initializeShellParsers ( ) ;
308304 try {
309305 const parsedObjArgs = shellParse ( command ) ;
310- if ( parsedObjArgs . some ( ( arg ) => typeof arg === 'object' ) ) return decision ;
311- const parsedArgs = parsedObjArgs . map ( String ) ;
312- if ( isDangerousCommand ( parsedArgs ) ) {
306+ const parsedArgs = parsedObjArgs . map ( extractStringFromParseEntry ) ;
307+
308+ if ( this . sandboxManager . isDangerousCommand ( parsedArgs ) ) {
313309 debugLogger . debug (
314310 `[PolicyEngine.check] Command evaluated as dangerous, forcing ASK_USER: ${ command } ` ,
315311 ) ;
316312 return PolicyDecision . ASK_USER ;
317313 }
318- const isApprovedBySandbox =
319- this . toolSandboxEnabled &&
320- this . sandboxApprovedTools . includes ( parsedArgs [ 0 ] ) ;
314+
321315 if (
322- ( isKnownSafeCommand ( parsedArgs ) || isApprovedBySandbox ) &&
316+ this . sandboxManager . isKnownSafeCommand ( parsedArgs ) &&
323317 decision === PolicyDecision . ASK_USER
324318 ) {
325319 debugLogger . debug (
0 commit comments