CVE-2026-43961: Vim: vimscript injection via unescaped filename in netrw s:netrwmarkfile() filter() expression allows arbitrary code execution
A flaw was found in Vim's netrw plugin. A crafted filename containing quote characters and expression fragments can break out of the quoted context during mark/unmark operations, allowing arbitrary Vimscript execution. This can be leveraged to run shell commands with the privileges of the user running Vim.
Other sources
AIONLYREPORT package: vim-9.1.083-9.el102 ------ Summary: Vimscript injection via unescaped filename in filter() expression in s:NetrwMarkFile(): a crafted filename can break out of the quoted filter() expression during netrw mark/unmark operations and execute arbitrary Vimscript, which can in turn invoke shell commands with the privileges of the Vim user. Requirements to exploit: The attacker must place or induce access to a crafted filename in a directory the victim browses with netrw. The victim must open that directory in Vim and trigger mark/unmark on the malicious entry. Successful exploitation executes attacker-controlled Vimscript and any shell commands it invokes with the privileges of the Vim process. Component affected: Vim netrw implementation - vim91/runtime/autoload/netrw.vim (s:NetrwMarkFile()) Version affected: confirmed in vim-9.1.083-9.el102; available local history shows the vulnerable code from boundary commit e00d3d2 (base vim-9.1.083-9.el10) through current HEAD Patch available: no Version fixed (if any already): unknown Upstream coordination: Not yet notified. This report is the initial triage, and a draft disclosure email is prepared for maintainers. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - 7.8 (HIGH) AV:L - The attacker must control or induce access to a crafted filename in a directory the victim opens locally through Vim/netrw. AC:L - Exploitation requires only crafted filename content; no race condition or special environment is needed beyond using netrw mark/unmark. PR:N - The attacker needs no privileges on the vulnerable Vim instance. UI:R - The victim must browse the directory in netrw and trigger mark/unmark on the crafted entry. S:U - The vulnerable component and the impact remain within the Vim user context. C:H - Arbitrary Vimscript can read files and data accessible to the user running Vim. I:H - Arbitrary Vimscript can modify files or invoke shell commands as that user. A:H - Arbitrary Vimscript or shell commands can disrupt the editor session or destroy user-accessible data. Impact: Important. Successful exploitation leads to arbitrary Vimscript and shell command execution with the privileges of the user running Vim. Although exploitation requires local file placement and explicit user interaction inside netrw, it directly compromises the confidentiality, integrity, and availability of the user's data and environment. Embargo: yes Reason: This issue permits code execution from a crafted filename and no official fix is known yet. Public disclosure before coordination or a fix is available would make social-engineering attacks against users browsing untrusted directories with netrw substantially easier. Suggested public date: 19-Jul-2026 Acknowledgement: Aisle Research
Vulnerability details
In vim91/runtime/autoload/netrw.vim, a:fname from the directory listing is composed into dname and then interpolated directly into a string expression passed to filter(): vim let dname= s:ComposePath(b:netrwcurdir,a:fname) ... call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"') filter({list}, {expr}) evaluates {expr} when it is supplied as a string. A crafted filename containing " and expression fragments can therefore break out of the quoted string during mark/unmark and execute arbitrary Vimscript. Relevant flow: vim nnoremap ... mf :...call <SID>NetrwMarkFile(...,<SID>NetrwGetWord())<cr> fun! s:NetrwGetWord() let dirname= getline('.') return dirname endfun Most relevant CWE identifiers: CWE-94 (Improper Control of Generation of Code)
CWE-74 (Injection into downstream interpreter)
Affected versions
Using available repository history in this checkout: git blame -L 7000,7040 vim91/runtime/autoload/netrw.vim attributes the vulnerable lines to boundary commit e00d3d2 (base vim-9.1.083-9.el10).
Current HEAD in this checkout still contains the vulnerable code.
Based on the available history, the affected range appears to extend from e00d3d2 through current HEAD; earlier upstream introduction could not be confirmed from the truncated history.
Steps to reproduce
1. Create a test directory and a file whose name injects Vimscript into the quoted filter() expression: bash mkdir netrw-poc && cd netrw-poc python3 - <<'PY' from pathlib import Path name = 'x" . execute("silent! !touch netrwinjectionpoc") . "' Path(name).writetext("poc\n") print(name) PY 2. Open Vim in that directory and browse it with netrw (for example, :Ex). 3. Move the cursor to the crafted filename. 4. Press mf once to mark the file, then mf again to unmark it. 5. Observe the command-execution side effect: bash ls -l netrwinjectionpoc
Proposed fix
Use a lambda/Funcref so filter() does not parse attacker-controlled filename data as a Vimscript expression: diff — a/vim91/runtime/autoload/netrw.vim +++ b/vim91/runtime/autoload/netrw.vim @@ call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"') + call filter(s:netrwmarkfilelist, {, v -> v !=# dname})
Alternative safe string form: vim call filter(s:netrwmarkfilelist, 'v:val !=# ' . string(dname)) ------ This report was generated using AI technology. Always review AI-generated content prior to use
— Red Hat
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
debian/vimto a version that resolves this vulnerability.Fixed in 2:9.1.1230-2+deb13u1 - Upgrade
Upgrade
debian/vimto a version that resolves this vulnerability.Fixed in 2:9.2.0524-1 - Upgrade
Upgrade
debian/vimto a version that resolves this vulnerability.Fixed in 2:9.1.1230-2+deb13u1Fixed in 2:9.2.0858-1 - Upgrade
Upgrade
alpine/vimto a version that resolves this vulnerability.Fixed in 9.2.0481-r0 - Configuration
In vim91/runtime/autoload/netrw.vim, update s:NetrwMarkFile() to stop building a string expression for filter() with unescaped attacker-controlled dname (derived from a:fname). Instead, refactor the filter call to use a lambda/Funcref/function so {expr} is not provided as a quoted string (current vulnerable patterns include filter(s:netrwmarkfilelist, 'v:val !=# ' . '"' . dname . '"') / filter(..., {expr} as a string).
Vim netrw plugin (vim91/runtime/autoload/netrw.vim) filter() expression in s:NetrwMarkFile()/mark-unmark path = Use a lambda/Funcref so filter() does not parse attacker-controlled filename data as a Vimscript expression (avoid string form of {expr}) - Compensating control
As a mitigation until the netrw change is applied, avoid marking/unmarking files with netrw in directories that may contain attacker-controlled crafted filenames (e.g., directories you do not fully trust) because exploitation requires only a crafted filename entry in a local directory opened through Vim/netrw, followed by triggering netrw mark/unmark.
Event History
Frequently Asked Questions
Who is exposed to this issue?
Users who browse attacker-controlled or otherwise untrusted directories with Vim's netrw plugin are exposed. Exploitation runs code with the privileges of the user running Vim.
What must an attacker and victim do for exploitation to succeed?
An attacker must place a crafted filename, containing quote characters and expression fragments, in a directory that the victim accesses with netrw. The victim must open that directory in Vim and use netrw's mark or unmark operation on the malicious entry.
How can I determine whether my environment is affected?
The issue is confirmed in vim-9.1.083-9.el10_2, in netrw's s:NetrwMarkFile() implementation in vim91/runtime/autoload/netrw.vim. Systems where users use netrw to mark or unmark files in directories containing untrusted filenames should be treated as exposed until the installed package version is verified against vendor remediation information.