* Check if a command is allowed based on config patterns
(command: string)
| 266 | * Check if a command is allowed based on config patterns |
| 267 | */ |
| 268 | function isCommandAllowed(command: string): {allowed: boolean; reason?: string} { |
| 269 | const config = getExecConfig(); |
| 270 | const allowPatterns = config.allow || []; |
| 271 | const denyPatterns = config.deny || []; |
| 272 | |
| 273 | // Check default blocked patterns unless allowUnsafe is explicitly set |
| 274 | if (!config.allowUnsafe) { |
| 275 | for (const {pattern, reason} of DEFAULT_BLOCKED) { |
| 276 | if (pattern.test(command)) { |
| 277 | return {allowed: false, reason}; |
| 278 | } |
| 279 | } |
| 280 | } |
| 281 | |
| 282 | // Check user-configured deny patterns (takes precedence over allow) |
| 283 | for (const pattern of denyPatterns) { |
| 284 | if (matchesPattern(command, pattern)) { |
| 285 | return {allowed: false, reason: `Command matches deny pattern: ${pattern}`}; |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | // If no allow patterns configured, allow by default (unless denied above) |
| 290 | if (allowPatterns.length === 0) { |
| 291 | return {allowed: true}; |
| 292 | } |
| 293 | |
| 294 | // Check if matches any allow pattern |
| 295 | const isAllowed = allowPatterns.some((pattern) => matchesPattern(command, pattern)); |
| 296 | if (!isAllowed) { |
| 297 | return {allowed: false, reason: 'Command not in allow list'}; |
| 298 | } |
| 299 | |
| 300 | return {allowed: true}; |
| 301 | } |
| 302 | |
| 303 | interface ExecuteResult { |
| 304 | stdout: string; |
no test coverage detected