[LFS Trac] #5956: vim-9.2.0663 (Security Update)
"LFS Trac" ([email protected] via lfs-book Mailing List) <[email protected]> Wed, 17 Jun 2026 18:55:20 -0000
| Newsgroups | gmane.linux.lfs.book |
|---|---|
| Message-ID | <[email protected]> |
#5956: vim-9.2.0663 (Security Update)
-------------------------+----------------------
Reporter: Joe Locash | Owner: lfs-book
Type: enhancement | Status: new
Priority: normal | Milestone: 13.1
Component: Book | Version: git
Severity: normal | Keywords:
-------------------------+----------------------
There have been a few security updates since the last book update:
{{{
Out-of-bounds Write in Spell File Word Count in Vim < 9.2.0653
==============================================================
Date: 15.06.2026
Severity: Medium
CVE: *requested, not yet assigned*
CWE: Out-of-bounds Write (CWE-787)
## Summary
The `tree_count_words()` function in `src/spellfile.c` fills in the word-
count
fields of a spell-file word trie by walking it iteratively with a depth
counter. The counter is bounded only by the trie structure itself; it is
never checked against the size of the fixed `MAXWLEN`-element stack arrays
it
indexes (`arridx[]`, `curi[]`, `wordcount[]`). A crafted `.spl`/`.sug`
file
pair, loaded when the user invokes spell suggestion, can drive the descent
arbitrarily deep, so the function writes past the end of those arrays.
This
is a stack out-of-bounds write that corrupts the call frame and crashes
the
editor.
## Description
`tree_count_words()` is called from `suggest_load_files()` when spell
suggestion loads a language's `.sug` file (for example on `z=`,
`:spellsuggest`, or suggestion completion). For each node it descends one
level with:
```C
else
{
++depth;
arridx[depth] = idxs[n];
curi[depth] = 1;
wordcount[depth] = 0;
}
```
The three arrays have `MAXWLEN` (254) elements, so any `depth` of 254 or
more
writes out of bounds. In a well-formed file each trie level corresponds
to
one byte of a word, so depth is naturally limited, but the reader does not
enforce this for shared subtrees: `read_tree_node()` caps inline recursion
at
`depth > MAXWLEN`, yet a `BY_INDEX` shared reference is accepted (its
target
index is range-checked) and is *not* recursed into. A trie that uses
shared
references to form a cycle, or a deep forward-shared chain, therefore
parses
cleanly while driving the iterative walker past `MAXWLEN`.
## Impact
A spell file is normally inert data, but Vim resolves `spelllang`,
`spellfile`, and `runtimepath` to load it, so a repository or archive that
ships a malicious `spell/` sidecar can deliver the crafted pair. The
trigger
is user-interaction-gated: spell checking must be enabled and the user
must
invoke spell suggestion on a misspelled word. When that happens, the
out-of-bounds write corrupts the `tree_count_words()` stack frame. On
builds
compiled with stack protection the overwrite is caught at the function
epilogue
and the process aborts; cyclic geometries instead walk into the stack
guard
page and causes a crash.
## Acknowledgements
The Vim project would like to thank Cipher / Causal Security
(https://causalsecurity.com/) for reporting and analyzing the issue and
suggesting a fix.
## References
The issue has been fixed as of Vim patch
[v9.2.0653](https://github.com/vim/vim/releases/tag/v9.2.0653).
-
[Commit](https://github.com/vim/vim/commit/a80874d9b84a01040e3d1aef2d4a59e1934dafb7)
- [Github Security
Advisory](https://github.com/vim/vim/security/advisories/GHSA-
wgh4-64f7-q3jq)
}}}
{{{
Out-of-bounds Write in Spell File Prefix Dump in Vim < 9.2.0662
===============================================================
Date: 16.06.2026
Severity: Medium
CVE: *requested, not yet assigned*
CWE: Out-of-bounds Write (CWE-787)
## Summary
The `dump_prefixes()` function in `src/spell.c` walks a spell-file prefix
trie
iteratively with a depth counter while dumping the prefixes that apply to
a
word. The counter is bounded only by the trie structure itself; it is
never
checked against the size of the fixed `MAXWLEN`-element stack arrays it
indexes
(`prefix[]`, `arridx[]`, `curi[]`). A crafted `.spl` file, loaded when
the
user dumps the word list, can drive the descent arbitrarily deep, so the
function writes past the end of those arrays. This is a stack out-of-
bounds
write that corrupts the call frame and crashes the editor.
## Description
`dump_prefixes()` is called from `spell_dump_compl()` when the word list
is
dumped, for example on `:spelldump` or via spelling completion. For each
node
it descends one level with:
```C
else
{
prefix[depth++] = c;
arridx[depth] = idxs[n];
curi[depth] = 1;
}
```
The arrays have `MAXWLEN` (254) elements, so any `depth` of 254 or more
writes
out of bounds; a second sink underflows a `size_t` length passed to
`vim_strncpy()` once `depth` reaches `MAXWLEN`. In a well-formed file
each
trie level corresponds to one byte of a prefix, so depth is naturally
limited,
but the reader does not enforce this for shared subtrees: a `BY_INDEX`
shared
reference is accepted (its target index is range-checked) and is *not*
recursed
into. A prefix trie that uses a shared reference to point back to an
ancestor
or itself therefore parses cleanly while driving the iterative walker past
`MAXWLEN`. This is the same class of issue as
[GHSA-wgh4-64f7-q3jq](https://github.com/vim/vim/security/advisories/GHSA-
wgh4-64f7-q3jq)
(`tree_count_words()`, fixed in 9.2.0653) in a sibling trie walker that
was
left unguarded.
## Impact
A spell file is normally inert data, but Vim resolves `spelllang`,
`spellfile`,
and `runtimepath` to load it, so a repository or archive that ships a
malicious
`spell/` sidecar can deliver the crafted file. The trigger is
user-interaction-gated: spell checking must be enabled and the user must
dump
the word list. When that happens, the out-of-bounds write corrupts the
`dump_prefixes()` stack frame.
## Acknowledgements
The Vim project would like to thank Cipher / Causal Security
(https://causalsecurity.com/) for reporting and analyzing the issue and
suggesting a fix.
## References
The issue has been fixed as of Vim patch
[v9.2.0662](https://github.com/vim/vim/releases/tag/v9.2.0662).
- [Commit](https://github.com/vim/vim/commit/8325b193bba5f01e7a7d8241f)
- [Github Security
Advisory](https://github.com/vim/vim/security/advisories/GHSA-qm9w-fmpj-
879h)
}}}
{{{
Vimscript Code Injection in netrw NetrwLocalRmFile() via crafted filename
affects Vim < 9.2.0663
================================================================================================
Date: 16.06.2026
Severity: Medium
CVE: *requested, not yet assigned*
CWE: Improper Control of Generation of Code (CWE-94) /
Improper Neutralization of Special Elements used in an OS Command
('OS Command Injection') (CWE-78)
## Summary
A Vimscript code injection vulnerability exists in `s:NetrwLocalRmFile()`
in
the netrw plugin (`runtime/pack/dist/opt/netrw/autoload/netrw.vim`) when
deleting a local file from the browser. A filename derived from the
buffer's
directory listing is interpolated into an Ex command line passed to
`:execute` with only the backslash character escaped, allowing a crafted
filename containing a bar (`|`) to terminate the intended command and
execute
arbitrary Vimscript, including shell commands via `:call system()` and
`:!`.
## Description
`s:NetrwLocalRmFile()` removes a file and wipes its buffer. The sibling
sinks
in the same file guard the Ex context with `fnameescape()`, for example:
exe "sil! keepj keepalt file ".fnameescape(a:newname)
The delete handler, however, escapes only the backslash character and
passes
the value straight to `:execute`:
let rmfile = s:NetrwFile(netrw#fs#ComposePath(a:path,
escape(a:fname, '\\')))->fnamemodify(':.')
...
execute printf('silent! bwipeout %s', rmfile)
`escape(a:fname, '\\')` neutralizes only `\`; the subsequent
`ComposePath`,
`NetrwFile`, and `fnamemodify` calls join and normalize the path but do
not
remove `|` or a newline. When the value reaches `:execute`, a `|`
terminates
the `bwipeout` command and begins the next, so the remainder of the
filename
is run as Ex commands. A file named `x|call system('cmd')|y` turns the
deletion into `silent! bwipeout x`, `call system('cmd')`, `y`, and the
injected `:call system(...)` runs an arbitrary shell command.
The filename reaches `s:NetrwLocalRmFile()` through the `D` mapping, which
reads the filename from the current line of the netrw directory listing
and,
after confirmation, deletes the entry.
## Impact
The vulnerability allows arbitrary Vimscript execution, and by extension
arbitrary shell command execution, with the privileges of the user running
Vim. Exploitation requires:
- a Unix-like system on which a filename may contain a bar (`|`),
- a crafted file present in a directory the victim browses with netrw, and
- the victim to delete that specific entry (press `D`, then confirm with
`y`).
The severity is rated Medium because exploitation requires a planted file
with
an unusual name and a deliberate delete action by the victim on that
specific
entry, although the resulting primitive is full command execution as the
victim user.
Note: due to the nature of the issue, it seems unlikely that a user would
delete such a suspicious filename.
## Acknowledgements
The Vim project would like to thank Cipher / Causal Security
(https://causalsecurity.com/) for reporting and analyzing the issue.
## References
The issue has been fixed as of Vim patch
[v9.2.0663](https://github.com/vim/vim/releases/tag/v9.2.0663).
-
[Commit](https://github.com/vim/vim/commit/55bc757a5d436e59d50fe43f7cda94b118f86cb2)
- [Github Security
Advisory](https://github.com/vim/vim/security/advisories/GHSA-vhh8-v6wx-
hjjh)
}}}
--
Ticket URL: <https://wiki.linuxfromscratch.org/lfs/ticket/5956>
LFS Trac <https://wiki.linuxfromscratch.org/lfs/>
Linux From Scratch: Your Distro, Your Rules.
--
http://lists.linuxfromscratch.org/sympa/info/lfs-book
Unsubscribe: See the above information page