Skip to content

Commit 725d97c

Browse files
authored
Merge pull request #2183 from dgageot/permissions3
Simplify pkg/permissions: extract helper, reduce type cases, remove redundant checks
2 parents a3e4acb + 58cf0c4 commit 725d97c

1 file changed

Lines changed: 22 additions & 30 deletions

File tree

pkg/permissions/permissions.go

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package permissions
55
import (
66
"fmt"
77
"path/filepath"
8-
"strconv"
98
"strings"
109

1110
"github.com/docker/docker-agent/pkg/config/latest"
@@ -85,30 +84,34 @@ func (c *Checker) Check(toolName string) Decision {
8584
// (e.g. read-only tools). Note that --yolo mode takes precedence over ForceAsk.
8685
func (c *Checker) CheckWithArgs(toolName string, args map[string]any) Decision {
8786
// Deny patterns are checked first - they take priority
88-
for _, pattern := range c.denyPatterns {
89-
if matchToolPattern(pattern, toolName, args) {
90-
return Deny
91-
}
87+
if matchAny(c.denyPatterns, toolName, args) {
88+
return Deny
9289
}
9390

9491
// Allow patterns are checked second
95-
for _, pattern := range c.allowPatterns {
96-
if matchToolPattern(pattern, toolName, args) {
97-
return Allow
98-
}
92+
if matchAny(c.allowPatterns, toolName, args) {
93+
return Allow
9994
}
10095

10196
// Explicit ask patterns override auto-approval (e.g. read-only hints)
102-
for _, pattern := range c.askPatterns {
103-
if matchToolPattern(pattern, toolName, args) {
104-
return ForceAsk
105-
}
97+
if matchAny(c.askPatterns, toolName, args) {
98+
return ForceAsk
10699
}
107100

108101
// Default is Ask
109102
return Ask
110103
}
111104

105+
// matchAny reports whether any pattern in the list matches the tool name and args.
106+
func matchAny(patterns []string, toolName string, args map[string]any) bool {
107+
for _, pattern := range patterns {
108+
if matchToolPattern(pattern, toolName, args) {
109+
return true
110+
}
111+
}
112+
return false
113+
}
114+
112115
// IsEmpty returns true if no permissions are configured
113116
func (c *Checker) IsEmpty() bool {
114117
return len(c.allowPatterns) == 0 && len(c.askPatterns) == 0 && len(c.denyPatterns) == 0
@@ -176,12 +179,7 @@ func matchToolPattern(pattern, toolName string, args map[string]any) bool {
176179
return true
177180
}
178181

179-
// If pattern has argument conditions but no args provided, no match
180-
if args == nil {
181-
return false
182-
}
183-
184-
// All argument patterns must match
182+
// All argument patterns must match (indexing a nil args map is safe in Go)
185183
for argName, argPattern := range argPatterns {
186184
argValue, exists := args[argName]
187185
if !exists {
@@ -203,16 +201,9 @@ func argToString(v any) string {
203201
switch val := v.(type) {
204202
case string:
205203
return val
206-
case bool:
207-
return strconv.FormatBool(val)
208204
case float64:
209-
// JSON numbers are float64 - format without trailing zeros
210-
if val == float64(int64(val)) {
211-
return strconv.FormatInt(int64(val), 10)
212-
}
205+
// JSON numbers are float64 - use %g for shortest representation
213206
return fmt.Sprintf("%g", val)
214-
case int, int64:
215-
return fmt.Sprintf("%d", val)
216207
default:
217208
return fmt.Sprintf("%v", v)
218209
}
@@ -237,10 +228,11 @@ func matchGlob(pattern, value string) bool {
237228

238229
// Handle trailing wildcard for prefix matching
239230
// This allows "sudo*" to match "sudo rm -rf /"
240-
if strings.HasSuffix(pattern, "*") && !strings.HasSuffix(pattern, "\\*") {
231+
if strings.HasSuffix(pattern, "*") {
241232
prefix := pattern[:len(pattern)-1]
242-
// If prefix contains no other glob characters, do simple prefix match
243-
if !strings.ContainsAny(prefix, "*?[") {
233+
// If prefix contains no other glob characters, do simple prefix match.
234+
// Including \ catches escaped asterisks (e.g. "foo\*").
235+
if !strings.ContainsAny(prefix, `*?[\`) {
244236
return strings.HasPrefix(value, prefix)
245237
}
246238
}

0 commit comments

Comments
 (0)