Hmbown/CodeWhale · error · anyhow::Error
persistent command allow rules must use exact matching
Error message
persistent command allow rules must use exact matching
What it means
append_allow_rules (crates/config/src/lib.rs:5264) rejects an allow rule that carries a command but has command_exact = false. Persistent command grants must use exact string matching so 'allow npm' can never widen into 'allow npm; curl evil.sh' via prefix/pattern semantics. Inexact matches are allowed only as session rules.
Source
Thrown at crates/config/src/lib.rs:5264
/// `permissions.toml` file.
///
/// The caller is responsible for deciding which tool calls are eligible;
/// this boundary rejects broad or incorrectly typed records so a UI bug
/// cannot persist an unscoped allow grant.
pub fn append_allow_rules(&mut self, rules: &[ToolAskRule]) -> Result<usize> {
for rule in rules {
if rule.action != PermissionAction::Allow {
bail!("append_allow_rules only accepts action = \"allow\"");
}
let Some(workspace) = rule
.workspace
.as_deref()
.and_then(codewhale_execpolicy::normalize_workspace_scope)
else {
bail!("persistent allow rules must be scoped to a workspace");
};
if rule.command.is_some() && !rule.command_exact {
bail!("persistent command allow rules must use exact matching");
}
if rule.command.is_none() && rule.path.is_none() {
bail!("persistent allow rules must match an exact command or path");
}
if let Some(command) = rule.command.as_deref()
&& command.trim().is_empty()
{
bail!("persistent command allow rules must not be empty");
}
if let Some(path) = rule.path.as_deref()
&& codewhale_execpolicy::normalize_workspace_relative_path(path, &workspace)
.is_none_or(|path| path.is_empty())
{
bail!("persistent path allow rules must stay within the workspace");
}
}
self.append_permission_rules(rules, PermissionAction::Allow)
}View on GitHub (pinned to 0c42157ee5)
Solutions
- Set command_exact = true and store the full exact command string that was approved
- If the user approved only a prefix/pattern, keep it session-scoped instead of persisting
- For path-based tools, persist a path rule instead of a command rule
Example fix
// before
let rule = ToolAskRule { command: Some(cmd.clone()), command_exact: false, /* ... */ };
// after
let rule = ToolAskRule { command: Some(cmd.clone()), command_exact: true, /* ... */ }; Defensive patterns
Strategy: validation
Validate before calling
assert!(rule.command.is_none() || rule.command_exact); // before append_allow_rules
Type guard
fn is_exact_command_rule(rule: &ToolAskRule) -> bool {
rule.command.as_deref().is_none_or(|_| rule.command_exact)
} Prevention
- Default command_exact to true in any rule constructor used for persistence
- Do not convert pattern/prefix session approvals into persistent rules
- Show the exact command string in the 'always allow' prompt so users approve the exact form
When it happens
Trigger: A ToolAskRule with command = Some("npm ...") and command_exact = false passed to append_allow_rules — e.g. a caller reusing a pattern-match session rule for persistence.
Common situations: UI persisting a prefix-matched approval, porting rules from a tool that allows glob commands, constructing rules from a deserialized older schema defaulting command_exact to false.
Related errors
- persistent allow rules must be scoped to a workspace
- persistent allow rules must match an exact command or path
- persistent command allow rules must not be empty
- persistent path allow rules must stay within the workspace
- {kind} must be a single path component
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/b5318372f9ccbd81.
Report an issue: GitHub.