Vim ships with a large library of helper scripts that quietly add convenience features — among them the ability to browse and unpack archive files directly from the editor. CVE-2026-46483 lives in one of those helpers. Recorded in the National Vulnerability Database, it is a command injection flaw in Vim’s tar plugin that can run shell commands when a user does nothing more dangerous than open a maliciously named archive. It is a low-severity bug by the numbers, but it is a clean illustration of how shell-escaping subtleties turn into code execution.

According to the NVD record, “prior to 9.2.0479, a command injection vulnerability exists in tar#Vimuntar() in runtime/autoload/tar.vim when decompressing .tgz archives on Unix-like systems.” The function’s job is to decompress a gzip-compressed tarball, which it does by shelling out to gunzip or gzip -d. The flaw is in how it constructs those shell commands: it “builds :!gunzip and :!gzip -d commands using shellescape(tartail) without the {special} flag, allowing a crafted archive filename to trigger Vim cmdline-special expansion and execute shell commands in the user’s context.” The fix landed in Vim 9.2.0479.

The CWE class: command and argument injection

NVD assigns two related weakness identifiers: CWE-78 (OS Command Injection) and CWE-88 (Improper Neutralization of Argument Delimiters in a Command, or ‘Argument Injection’). The pairing is apt. The end result is OS command execution (CWE-78), but the specific mechanism is a failure to neutralize special elements in a value that becomes part of a command line — the filename — which is the argument-injection family (CWE-88). The interesting part is why the escaping failed despite the developer calling an escaping function at all.

Vim’s shellescape() function quotes a string so it can be passed safely to a shell. But Vim’s command-line interface, the :! filter, performs its own layer of expansion on certain special characters before the shell ever sees the string — the behavior Vim documents as cmdline-special. Characters such as % (the current file name) and # (the alternate file name) are expanded by Vim itself within a :! command. To suppress that expansion, shellescape() must be called with its optional {special} argument set, which tells Vim to additionally escape those command-line-special characters. The vulnerable code called shellescape(tartail) without that flag. So even though the filename was quoted for the shell, Vim’s own pre-processing of the :! line could still expand special characters embedded in a crafted archive filename, injecting content into the command before it was handed off — and ultimately running attacker-chosen shell commands as the user.

Why the CVSS is 3.6 Low

The record carries a CVSS v3.1 base score of 3.6 (Low), vector AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N. Several factors hold the score down, and the vector lays them out. The attack vector is Local (AV:L): the victim must open a malicious .tgz on their own machine. Attack Complexity is High (AC:H) because exploitation depends on specific conditions — the user must be on a Unix-like system, must use Vim’s tar plugin to unpack the archive, and the attacker must craft a filename that survives into the special expansion. User Interaction is Required (UI:R), since the victim has to open the file. And the impacts are only Low for confidentiality and integrity with none for availability (C:L/I:L/A:N) as scored, reflecting a bounded assessment of what the injected command achieves in the rated scenario rather than the theoretical ceiling of arbitrary execution.

It is worth being candid that “executes shell commands in the user’s context” sounds worse than a 3.6 suggests, and the gap comes almost entirely from the high complexity and the local, user-interaction-gated delivery. The realistic threat model is a user who downloads or receives an archive from an untrusted source and unpacks it in Vim — a plausible but specific sequence. Defenders should weight the score against their own exposure: environments where users routinely open arbitrary archives in Vim warrant faster patching than the base number implies.

What is affected and how to remediate

The affected software is Vim prior to 9.2.0479 on Unix-like systems, specifically the bundled tar.vim autoload plugin’s .tgz handling. The remediation is to upgrade Vim to 9.2.0479 or later, which corrects the call to include the {special} flag so the filename is fully neutralized before the :! command is built. Most users will receive the fix through their operating-system package updates; those building Vim from source or pinning older runtime files should ensure the updated tar.vim is in place.

As interim hygiene, users should avoid unpacking archives from untrusted sources directly inside Vim, and should treat archive filenames — not just contents — as untrusted input, since this bug turns the name of the file into the injection vector. The broader lesson is one that recurs across shells and editors alike: calling an escaping function is not the same as escaping correctly. Layered interpreters — here, Vim’s command-line expansion sitting in front of the OS shell — each apply their own special-character rules, and a value must be neutralized for every layer it passes through. Vim provided the {special} flag precisely for this case; CVE-2026-46483 is what happens when it is omitted.

This bug also fits a recognizable pattern in Vim’s archive-handling helpers, which have historically been a recurring source of injection issues precisely because they bridge two interpreters: the editor’s own command language and the underlying shell. Each time a plugin shells out to gzip, tar, unzip, or a similar utility, it has to thread a value the user did not author — a path, a filename, an entry name — through both layers intact. The {special} flag exists exactly for that threading, and its omission here is a one-line slip with outsized consequences. For maintainers of any tool that constructs commands from filenames, the takeaway is to test escaping against hostile names containing every metacharacter the relevant layers treat specially, not just the ones the shell cares about.