init: fix command injection in bash Tab completion (compgen -W expansion) - #696
Merged
xdelaruelle merged 3 commits intoSep 7, 2026
Merged
Conversation
…ion) _module_comgen_words_and_files() fed untrusted text (module names read off disk, LOADEDMODULES, MODULEPATH) straight into `compgen -W`, which performs a full unquoted-word expansion on its wordlist -- including command substitution -- as a normal, documented part of its behavior. A module name, loaded-module entry, or MODULEPATH component containing e.g. `$(...)` therefore ran arbitrary shell code the moment a user pressed Tab. Fix: never hand candidate text to `compgen -W`. The new _module_comgen_words() splits the candidate list with `read -r -d ''` (pure IFS word-splitting, no expansion of any kind) and does the prefix match itself; _module_comgen_words_and_files() now layers the nospace-for-directory-entries behavior on top of it. Every call site that previously built a compgen -W wordlist from LOADEDMODULES, MODULEPATH, or a stash/save collection name now goes through one of these two functions instead. Fixes CVE-2026-85013 Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Xavier Delaruelle <xavier.delaruelle@cea.fr>
Adds injection-safety cases to the completion DejaGnu tool (testsuite/completion.00-init/021-bash.exp) covering the fix in the previous commit: a crafted module name, LOADEDMODULES entry, and MODULEPATH entry embedding shell code must be listed as an inert candidate string and never executed, verified by checking a marker file the payload would touch if it ran (completion_assert_no_exec, new in 006-procs.exp). Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Xavier Delaruelle <xavier.delaruelle@cea.fr>
…on fix The bash fix in a previous commit only applied to bash: the unquoted- word expansion compgen -W performs on its candidate string is specific to that one builtin. init/zsh-functions/_module.in hands candidates to 'compadd -a <array>', init/fish_completion to 'complete -a "(...)"' (newline-split command output), and init/tcsh_completion.in to a plain backtick command's word list -- in all three, each element becomes a literal candidate string with no further shell expansion, so none of them were ever vulnerable to this bug class. Add the same three injection-safety cases (a malicious module name, LOADEDMODULES entry, and MODULEPATH entry, each embedding shell code) to 031-zsh.exp/041-fish.exp/051-tcsh.exp, to guard against a future regression rather than a known vulnerability. Each shell has its own candidate-display conventions, which change what the literal "contains" check needs to look for: zsh backslash-escapes special characters before display/insertion, fish single-quotes a candidate containing a special character on single-candidate inline completion and (on a multi-candidate pager listing) strips a "(...)" suffix as if it were a candidate's own description, colliding with the embedded parentheses in the crafted candidate itself. fish has no MODULEPATH case: 'unuse' does not list modulepaths there at all. None of this affects the actual security check (completion_assert_no_exec, confirming that the crafted candidate's 'touch' side effect never ran), which needs no such per-shell handling. Also widens the completion timeout for the new section in 051-tcsh.exp: each case there spawns a cold tcsh session with nothing having already warmed up the pty/subprocess pipeline before listing candidates, which occasionally ran past the default 10 second bound under a loaded machine. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Xavier Delaruelle <xavier.delaruelle@cea.fr>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.