From 0725ed84e6bd52d9d004f214c83128090e117286 Mon Sep 17 00:00:00 2001 From: Paul Frederiksen Date: Fri, 24 Oct 2025 09:47:17 -0700 Subject: [PATCH] fix(completion): prevent script execution during tab completion Fixes #13366 - Tab completion after 'git' triggers bin/test execution Fixes #13310 - Duplicate completion candidates The 'l:|=* r:|=*' matcher pattern in completion.zsh was causing: 1. Unintended script execution during tab completion 2. Duplicate completion candidates 3. Overly permissive matching This pattern allowed left-side anchor matching which could cause zsh to execute scripts like bin/test when searching for completions. Removed 'l:|=* r:|=*' from all three configuration branches while preserving essential functionality: - Case-insensitive matching: m:{[:lower:][:upper:]}={[:upper:][:lower:]} - Right-side fuzzy matching: r:|=* - Hyphen-insensitive matching: m:{[:lower:][:upper:]-_}={[:upper:][:lower:]_-} Testing shows that completion continues to work correctly without the security and performance issues. --- lib/completion.zsh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/completion.zsh b/lib/completion.zsh index 3823c2544..21e7441ac 100644 --- a/lib/completion.zsh +++ b/lib/completion.zsh @@ -14,13 +14,19 @@ bindkey -M menuselect '^o' accept-and-infer-next-history zstyle ':completion:*:*:*:*:*' menu select # case insensitive (all), partial-word and substring completion +# NOTE: 'l:|=* r:|=*' matcher removed due to causing unexpected behavior: +# - Can trigger unintended execution of scripts during tab completion (issue #13366) +# - Causes duplicate completion candidates (issue #13310) +# - Creates overly permissive matching that degrades user experience +# The remaining matchers (case-insensitive + right-side anchor) provide all essential +# completion functionality without the problematic side effects. if [[ "$CASE_SENSITIVE" = true ]]; then - zstyle ':completion:*' matcher-list 'r:|=*' 'l:|=* r:|=*' + zstyle ':completion:*' matcher-list 'r:|=*' else if [[ "$HYPHEN_INSENSITIVE" = true ]]; then - zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]-_}={[:upper:][:lower:]_-}' 'r:|=*' 'l:|=* r:|=*' + zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]-_}={[:upper:][:lower:]_-}' 'r:|=*' else - zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|=*' 'l:|=* r:|=*' + zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|=*' fi fi unset CASE_SENSITIVE HYPHEN_INSENSITIVE