oss-sec mailing list archives
[vim-security] Arbitrary Ex Command Execution via File Names in C Omni-Completion in Vim < 9.2.1011
From: Christian Brabandt <cb () 256bit org>
Date: Tue, 25 Aug 2026 23:28:09 +0200
Arbitrary Ex Command Execution via File Names in C Omni-Completion in Vim < 9.2.1011
====================================================================================
Date: 25.08.2026
Severity: Medium
CVE: *requested, not yet assigned*
CWE: Improper Control of Generation of Code ('Code Injection') (CWE-94),
Inclusion of Functionality from Untrusted Control Sphere (CWE-829),
Improper Neutralization of Argument Delimiters in a Command ('Argument Injection') (CWE-88)
## Summary
The C omni-completion script in `runtime/autoload/ccomplete.vim` looks up
struct members by building a `:vimgrep` command and running it with
`:execute`. Besides the type name, that command line also holds the list of
tags file names returned by `tagfiles()`. Those names were escaped for the
space, the backslash, `#` and `%`, but not for the bar. Since `:vimgrep`
accepts another command after a bar, a file name whose name contains one
ends the `:vimgrep` command early and what follows is executed as an Ex
command when the user invokes omni-completion on a member access.
This is the same defect in the same command line as GHSA-cx73-phcg-3j5g,
fixed in patch [v9.2.0845](https://github.com/vim/vim/releases/tag/v9.2.0845),
which addressed only the type name. Unlike that issue, no crafted tags file
content is needed here: the file name itself carries the payload.
## Description
`runtime/ftplugin/c.vim` sets `omnifunc=ccomplete#Complete` on C buffers
when filetype plugins are enabled. When completing a member access, and the
declaration is not found in the buffer itself, `StructMembers()` searches the
tags files:
var fnames: string = tagfiles()
->map((_, v: string) => escape(v, ' \#%'))
->join()
...
execute 'silent! keepjumps noautocmd '
.. n .. 'vimgrep ' .. '/\t\V' .. escape(typename, '/\') .. '\m\(\t\|$\)/j '
.. fnames
`tagfiles()` returns the names of the tags files in effect for the buffer,
derived from the `'tags'` option. The names are appended unquoted to the
`:vimgrep` argument list.
The `:vimgrep` command is defined with the `EX_TRLBAR` flag, so a bar ends
the command and starts a new one. A bar in a file name is therefore not
part of the name but a command separator, and the remainder of the line is
parsed and executed as an independent Ex command by the same `:execute`.
Escaping the space limits what such a command can contain, but does not
prevent it, and `ccomplete.vim` is a `vim9script` file, so the injected text
is parsed with Vim9 syntax. The leading `:silent!` suppresses the resulting
error, so the injected command runs without a visible failure.
The issue has been addressed by escaping the bar in the tags file names as
well.
## Impact
Arbitrary Ex command execution, and through commands such as `:!` arbitrary
operating-system command execution, in the context of the user running Vim.
Exploitation requires:
- Vim with filetype plugins enabled
- a tags file whose path contains a bar, for example because it is stored in
a directory whose name contains one, and a `'tags'` value under which that
file is found,
- the victim opening a C file from that tree and invoking omni-completion
with `CTRL-X CTRL-O` on a member access whose type is only known from the
tags file.
The severity is rated Medium. The payload travels in a path rather than in
file content, so it is not visible to review that inspects files only. On
the other hand a bar in a directory name is unusual and conspicuous, it is
not a valid character in file names on MS-Windows, and the crafted name has
no effect until the user deliberately invokes omni-completion on a type that
is not declared in the edited buffer, since the completion would otherwise
not consult the tags files at all.
## Acknowledgements
The Vim project would like to thank Yazan Balawneh, Cystack.ps for reporting
the issue.
## References
The issue has been fixed as of Vim patch [v9.2.1011](https://github.com/vim/vim/releases/tag/v9.2.1011).
- [Commit](https://github.com/vim/vim/commit/331d5d67028505c5b6043603a57d1e8497b922b5)
- [Github Security Advisory](https://github.com/vim/vim/security/advisories/GHSA-r77m-8m55-rpr6)
Best,
Christian
--
Auge um Auge - und die ganze Welt wird blind sein.
-- Mahatma Gandhi
Current thread:
- [vim-security] Arbitrary Ex Command Execution via File Names in C Omni-Completion in Vim < 9.2.1011 Christian Brabandt (Aug 25)
