@@ -389,9 +389,10 @@ function buildMcpToolNamePrefixes(serverNames: readonly string[]): string[] {
389389 . filter ( Boolean ) ;
390390}
391391
392- function entriesMatchAnyMcpTool (
392+ function entriesMatchMcpTool (
393393 entries : readonly string [ ] ,
394394 serverNames : readonly string [ ] ,
395+ mode : "any" | "every" ,
395396) : boolean {
396397 const normalizedEntries = entries . map ( normalizeToolName ) . filter ( Boolean ) ;
397398 if (
@@ -402,23 +403,43 @@ function entriesMatchAnyMcpTool(
402403 return true ;
403404 }
404405 const serverPrefixes = buildMcpToolNamePrefixes ( serverNames ) ;
405- if (
406- normalizedEntries . some ( ( entry ) =>
407- serverPrefixes . some ( ( prefix ) => entry . length > prefix . length && entry . startsWith ( prefix ) ) ,
408- )
409- ) {
410- return true ;
411- }
412406 const patterns = compileGlobPatterns ( { raw : normalizedEntries , normalize : normalizeToolName } ) ;
413- if ( patterns . length === 0 ) {
414- return false ;
407+ const probeNames = buildMcpProbeToolNames ( serverNames ) . map ( normalizeToolName ) ;
408+ const prefixOrPatternMatches = ( prefix : string , index : number ) =>
409+ normalizedEntries . some ( ( entry ) => entry . length > prefix . length && entry . startsWith ( prefix ) ) ||
410+ matchesAnyGlobPattern ( probeNames [ index ] ?? "" , patterns ) ;
411+ return mode === "every"
412+ ? serverPrefixes . every ( ( prefix , index ) => prefixOrPatternMatches ( prefix , index ) )
413+ : serverPrefixes . some ( ( prefix , index ) => prefixOrPatternMatches ( prefix , index ) ) ;
414+ }
415+
416+ function entriesMatchAnyMcpTool (
417+ entries : readonly string [ ] ,
418+ serverNames : readonly string [ ] ,
419+ ) : boolean {
420+ return entriesMatchMcpTool ( entries , serverNames , "any" ) ;
421+ }
422+
423+ function entriesMatchEveryMcpTool (
424+ entries : readonly string [ ] ,
425+ serverNames : readonly string [ ] ,
426+ ) : boolean {
427+ return entriesMatchMcpTool ( entries , serverNames , "every" ) ;
428+ }
429+
430+ function sandboxPolicyAllowsAllMcpServers (
431+ policy : unknown ,
432+ serverNames : readonly string [ ] ,
433+ ) : boolean {
434+ const allow = getList ( policy , "allow" ) ;
435+ if ( Array . isArray ( allow ) && allow . length === 0 ) {
436+ return true ;
415437 }
416- return buildMcpProbeToolNames ( serverNames ) . some ( ( probeName ) =>
417- matchesAnyGlobPattern ( normalizeToolName ( probeName ) , patterns ) ,
418- ) ;
438+ const entries = [ ...( allow ?? [ ] ) , ...( getList ( policy , "alsoAllow" ) ?? [ ] ) ] ;
439+ return entriesMatchEveryMcpTool ( entries , serverNames ) ;
419440}
420441
421- function sandboxAllowGateAllowsMcp ( policy : unknown , serverNames : readonly string [ ] ) : boolean {
442+ function toolPolicyAllowsAnyMcpServer ( policy : unknown , serverNames : readonly string [ ] ) : boolean {
422443 const allow = getList ( policy , "allow" ) ;
423444 if ( Array . isArray ( allow ) && allow . length === 0 ) {
424445 return true ;
@@ -427,16 +448,20 @@ function sandboxAllowGateAllowsMcp(policy: unknown, serverNames: readonly string
427448 return entriesMatchAnyMcpTool ( entries , serverNames ) ;
428449}
429450
430- function sandboxPolicyIntentionallyDeniesMcp (
451+ function toolPolicyDeniesAllMcpServers ( policy : unknown , serverNames : readonly string [ ] ) : boolean {
452+ const deny = getList ( policy , "deny" ) ?? [ ] ;
453+ return entriesMatchEveryMcpTool ( deny , serverNames ) ;
454+ }
455+
456+ function sandboxPolicyIntentionallyDeniesAllMcpServers (
431457 policy : unknown ,
432458 serverNames : readonly string [ ] ,
433459) : boolean {
434- const deny = getList ( policy , "deny" ) ?? [ ] ;
435- return entriesMatchAnyMcpTool ( deny , serverNames ) ;
460+ return toolPolicyDeniesAllMcpServers ( policy , serverNames ) ;
436461}
437462
438463function nonSandboxToolPolicyBlocksMcp ( policy : unknown , serverNames : readonly string [ ] ) : boolean {
439- if ( sandboxPolicyIntentionallyDeniesMcp ( policy , serverNames ) ) {
464+ if ( toolPolicyDeniesAllMcpServers ( policy , serverNames ) ) {
440465 return true ;
441466 }
442467 const allow = getList ( policy , "allow" ) ;
@@ -453,7 +478,7 @@ function profileToolPolicyBlocksMcp(policy: unknown, serverNames: readonly strin
453478 resolveToolProfilePolicy ( profile ) ,
454479 getList ( policy , "alsoAllow" ) ,
455480 ) ;
456- return Boolean ( profilePolicy && ! sandboxAllowGateAllowsMcp ( profilePolicy , serverNames ) ) ;
481+ return Boolean ( profilePolicy && ! toolPolicyAllowsAnyMcpServer ( profilePolicy , serverNames ) ) ;
457482}
458483
459484function nonSandboxToolPoliciesBlockMcp ( params : {
@@ -515,8 +540,8 @@ function collectSandboxMcpAllowlistWarnings(cfg: OpenClawConfig): string[] {
515540 const issueSources = sandboxPolicies
516541 . filter (
517542 ( { policy } ) =>
518- ! sandboxAllowGateAllowsMcp ( policy , serverNames ) &&
519- ! sandboxPolicyIntentionallyDeniesMcp ( policy , serverNames ) ,
543+ ! sandboxPolicyAllowsAllMcpServers ( policy , serverNames ) &&
544+ ! sandboxPolicyIntentionallyDeniesAllMcpServers ( policy , serverNames ) ,
520545 )
521546 . filter ( ( { nonSandboxToolPolicyBlocksMcp } ) => ! nonSandboxToolPolicyBlocksMcp )
522547 . flatMap ( ( { labels } ) => labels ) ;
0 commit comments