Fix config rules not matching commands with global flags#137
Fix config rules not matching commands with global flags#137berk-karaal wants to merge 2 commits into
Conversation
Config rules like "allow git commit" failed to match "git -C /path commit" because _match_words() matched against raw tokens where global flags broke the prefix match. Add a two-pass approach: step 1 matches raw tokens (preserving explicit rules like "deny git -C * commit"), step 1.5 strips handler-recognized global flags and re-matches if step 1 found nothing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The two-pass shape here is nice — matching raw tokens first means explicit rules like It reuses each handler's full
And because the description strips these flags too, the user never sees them in the prompt — so their This bumps against the core philosophy in the security model — "approve what we know is safe; anything not explicitly safe requires approval." Matching on the stripped skeleton approves the command without ever examining the part that was removed. It's not only a malicious-injection concern either: I think the fix is to split the strippable set: flags that only relocate ( |
Summary
Fixes #136
Config rules like
allow git commitfail to match commands with global flags such asgit -C /path commit. This happens because the config matcher operates on raw tokens, where-C /pathbreaks the prefix match — even though Dippy displays the command as "git commit" when asking for permission (fixed in #17).Approach: Two-Pass Config Matching
deny git -C * commit.GLOBAL_FLAGS_WITH_ARG/GLOBAL_FLAGS_NO_ARGconstants and re-match.This ensures the config matcher recognizes the same command the user sees in the permission prompt.
Changes
src/dippy/cli/__init__.py: Addedstrip_global_flags()— reads global flag constants from handlers viagetattr(), strips them from tokens, returns cleaned tokens orNoneif no change.src/dippy/core/analyzer.py: Added step 1.5 between config matching and wrapper command handling. Extracted_config_match_decision()helper to deduplicate the match-to-decision conversion.Test plan
strip_global_flags()covering git, docker, unknown commands, and edge cases (tests/test_strip_global_flags.py)analyze()verifying end-to-end behavior including precedence of explicit flag rules (tests/test_analyzer_bugs.py::TestConfigGlobalFlagStripping)just checkpasses🤖 Generated with Claude Code