Apr 8, 2026·6 min read·3 visits
Vim versions prior to 9.2.0073 improperly sanitize hostname components in the netrw plugin. This oversight permits OS command injection via unescaped shell metacharacters during remote file operations, leading to arbitrary code execution under the user's privileges.
An OS command injection vulnerability exists within the bundled netrw plugin of the Vim text editor. Insufficient validation of URI hostnames allows local attackers to execute arbitrary shell commands when a user interacts with a crafted payload.
Vim includes a standard plugin called netrw, which provides remote file transfer and directory browsing capabilities. The plugin processes URIs using handlers like scp://, ftp://, and dav:// by dynamically invoking external system binaries. This component operates transparently when users attempt to read or write network-hosted files.
A flaw exists in how the netrw plugin validates and processes the hostname components of provided URIs. The vulnerability is classified as Improper Neutralization of Special Elements used in an OS Command (CWE-78). By embedding specific shell metacharacters within the hostname string, an attacker alters the structure of the resulting shell command.
The attack surface requires direct user interaction. A targeted user must open a maliciously crafted URI either via the command line or from within an active editor session. Successful exploitation results in the execution of arbitrary shell commands within the operating system context of the Vim process.
The vulnerability stems from the URI parsing and command construction logic within the netrw plugin. When handling network operations, the plugin dynamically builds shell commands to interface with external utilities such as ssh or scp. Hostnames extracted from the URI flow directly into these constructed command strings.
The primary failure occurs in the internal validation function s:NetrwValidateHostname(). The implementation originally relied on the unanchored regular expression a:hostname =~? '^[a-z0-9]'. This regex merely verified the presence of an alphanumeric character at the beginning of the string, failing to restrict the remainder of the input payload.
Because the regex lacked an end-of-string anchor, an attacker could append shell metacharacters, including semicolons, pipes, and backticks, immediately following the valid leading character. The plugin accepted these malformed strings as legitimate hostnames and processed them further in the pipeline.
The secondary failure resides in the command construction function s:MakeSshCmd(). The plugin substituted the unvalidated hostname into the final execution string without passing it through Vim's built-in shellescape() function. The raw injection payload subsequently executed when Vim invoked the system() call or the :r! command.
The vulnerable state of netrw.vim allowed malformed input to bypass sanitization. The implementation of s:NetrwValidateHostname() incorrectly accepted strings carrying executable commands, while s:MakeSshCmd() failed to safely quote the extracted variables.
" Vulnerable Code (Prior to 9.2.0073)
function s:NetrwValidateHostname(hostname)
" Flawed regex: Only checks the first character, no end anchor ($)
return a:hostname =~? '^[a-z0-9]'
endfunction
function s:MakeSshCmd(sshcmd)
if s:user == ""
let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',s:machine,'')
else
let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',s:user."@".s:machine,'')
endif
" s:machine is passed without shellescape() applied
endfunctionThe remediation introduced in commit 79348dbbc09332130f4c860 completely rewrites the validation logic. The patch replaces the flawed regex with strict, anchored regular expressions compliant with RFC1123 definitions. The updated patterns strictly match usernames, hostnames, IPv4, and IPv6 formats.
" Patched Code (9.2.0073)
function s:NetrwValidateHostname(hostname)
let user_pat = '\%([a-zA-Z0-9._-]\+@\)\?'
let host_pat = '[a-zA-Z0-9]\%([-a-zA-Z0-9.]\{,62}[a-zA-Z0-9]\)\?$'
let ipv4_pat = '\%(\d\{1,3}\.\)\{3}\d\{1,3}$'
let ipv6_pat = '\[\?\%([a-fA-F0-9:]\{2,}\)\+\]\?$'
" Validates against strict, anchored patterns
return a:hostname =~? '^'.user_pat.host_pat ||
\ a:hostname =~? '^'.user_pat.ipv4_pat ||
\ a:hostname =~? '^'.user_pat.ipv6_pat
endfunction
function s:MakeSshCmd(sshcmd)
" Mandatory shell escaping applied to machine variable
let machine = shellescape(s:machine, 1)
if s:user != ''
let machine = shellescape(s:user, 1).'@'.machine
endif
let sshcmd = substitute(a:sshcmd,'\<HOSTNAME\>',machine,'')
endfunctionExploitation requires direct local interaction by the targeted user. The attacker must induce the victim to process a malicious URI containing the injected OS command. The attacker generally achieves this by presenting the payload as a file path or URL for the user to edit or read.
The payload activates through normal Vim usage patterns. A user executes the command line vim "scp://localhost;touch /tmp/vulnerable;/@localhost/" or runs the equivalent :e command from an active buffer. The netrw plugin automatically initiates the protocol handler to fetch the requested resource.
The plugin constructs the underlying shell command with the unescaped payload embedded directly inside. Instead of connecting to a remote host, the system shell terminates the ssh sequence at the injected semicolon and sequentially executes the attacker's trailing shell commands.
Exploiting this vulnerability grants an attacker arbitrary code execution privileges. The injected commands run precisely under the context of the user executing the Vim process. The attacker inherits the filesystem access rights, environment variables, and active authentication tokens of the victim.
The CVSS v3.1 base score is 4.4 (Medium), designated by the vector CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N. The score accurately reflects the local attack vector, the low attack complexity, and the mandatory user interaction required to trigger the payload execution.
While the scope remains localized to the targeted user account, the vulnerability provides a highly effective vector for spear-phishing or lateral movement. Attackers frequently leverage client-side execution flaws to establish persistent backdoor access or to exfiltrate sensitive files currently manipulated within the development environment.
The Exploit Prediction Scoring System (EPSS) rating sits at 0.00012, representing a 1.80% percentile likelihood of imminent exploitation. At the time of disclosure, no active exploitation campaigns utilize this technique, and it does not appear within the CISA Known Exploited Vulnerabilities catalog.
The definitive remediation for CVE-2026-28417 requires updating the Vim installation to version 9.2.0073 or later. System administrators must deploy the updated packages from their respective operating system distribution repositories. The patch comprehensively neutralizes the injection vector by enforcing strict URI format compliance.
Environments unable to immediately deploy the updated binary can fully mitigate the vulnerability by disabling the netrw plugin. This workaround explicitly shuts down the vulnerable attack surface while preserving the core functionality of the text editor.
Users disable the plugin by defining g:loaded_netrw = 1 and g:loaded_netrwPlugin = 1 within their initialization file (typically ~/.vimrc or ~/.config/nvim/init.vim). This configuration prevents the editor from loading the vulnerable Vimscript files during startup.
As a defense-in-depth practice, developers should verify the integrity of external URIs before opening them. Security engineers should configure endpoint detection tools to monitor shell execution histories for anomalous invocations of scp, ftp, or ssh commands branching directly from editor processes.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Vim Vim | < 9.2.0073 | 9.2.0073 |
| Attribute | Detail |
|---|---|
| Vulnerability Class | OS Command Injection (CWE-78) |
| Attack Vector | Local (User Interaction Required) |
| CVSS v3.1 Score | 4.4 (Medium) |
| EPSS Score | 0.00012 (1.80%) |
| Impact | Arbitrary Code Execution under user process context |
| Exploitation Status | Proof-of-Concept Available |
| CISA KEV | Not Listed |
The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command.