macvim-dev / macvim-dev/macvim
[Security] MacVim affected by CVE-2026-43961 — netrw NetrwMarkFile() Vimscript injection via crafted filename (vim < 9.2.0480)
まだ誰も着手していません。
- 主要言語
- Vim Script
- スター
- 7.9k
- フォーク
- 691
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
[Security] MacVim affected by CVE-2026-43961 — netrw NetrwMarkFile() Vimscript injection via crafted filename (vim < 9.2.0480)
Summary
MacVim bundles the vim source at version 9.2 (patches 1-321 in the current build), which is
below the patched version 9.2.0480 that fixes CVE-2026-43961.
Vulnerability Details
- Upstream CVE: CVE-2026-43961
- Inherited from:
vim/vim - Affected code:
runtime/autoload/netrw.vim—s:NetrwMarkFile()function - Vulnerability type: CWE-94 — Improper Control of Generation of Code (Code Injection)
- Fixed in: vim 9.2.0480 (commit
8af0f098c3a42a28661d0295364e6e0fd7dbc92c)
Root Cause
In s:NetrwMarkFile() in runtime/autoload/netrw.vim, the global mark file list is
filtered using string interpolation of a user-controlled path:
" runtime/autoload/netrw.vim (macvim r183, line 5220)
let dname= netrw#fs#ComposePath(b:netrw_curdir,a:fname)
...
" remove new filename from global markfilelist
call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"')
dname is composed from the current directory and the filename under the cursor (a:fname).
The filter() call evaluates its second argument as a Vimscript expression. Because dname
is interpolated directly into that expression string using '"'.dname.'"', a filename
containing a " character can escape the string context and inject arbitrary Vimscript.
Attack Scenario
- An attacker places a file named
foo"+system('id')+"barin a directory. - The victim opens that directory in netrw inside MacVim.
- The victim presses
mfto mark the file (adds it to the global mark list). - The victim presses
mfagain to unmark the file — this triggers line 5220. - The
filter()call evaluates:filter(s:netrwmarkfilelist, 'v:val != "foo"+system(''id'')+"bar"') system('id')(or any arbitrary Vimscript/shell command) executes.
This can be triggered without any special permissions; any file accessible to the user
suffices. The attack is particularly relevant when opening untrusted project directories.
Affected MacVim Code
MacVim's runtime/pack/dist/opt/netrw/autoload/netrw.vim contains the vulnerable
s:NetrwMarkFile() function. The vulnerable line is:
" netrw.vim line 5220 (macvim r183)
call filter(s:netrwmarkfilelist,'v:val != "'.dname.'"')
Note: line 5179 (buffer-local list) uses 'v:val != a:fname' (variable reference, safe).
Only the global markfilelist at line 5220 is vulnerable.
The upstream fix (vim 9.2.0480) replaces the string interpolation with a lambda:
" Fixed form (vim >= 9.2.0480)
call filter(s:netrwmarkfilelist, {_, v -> v !=# dname})
The lambda form passes dname as a closed-over variable, never interpolating it into
an evaluated expression string.
neovim is NOT affected — its runtime/pack/dist/opt/netrw/autoload/netrw.vim already
uses the lambda form (lines 5167 and 5207).
Affected MacVim Version
MacVim r183 (vim 9.2 patches 1-321) — current HEAD as of 2026-05-18.
The fix commit 8af0f098c3a42a28661d0295364e6e0fd7dbc92c from vim/vim is not present
in the macvim-dev/macvim repository:
git log --all --oneline | grep 8af0f098 # returns no output
Suggested Fix
Merge or cherry-pick vim/vim patches up to at least 9.2.0480:
The fix changes the string-interpolated filter() expression to a lambda closure, which
avoids evaluating user-controlled data as Vimscript.
References
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
runtime/pack/dist/opt/netrw/autoload/netrw.vim から始めて s:NetrwMarkFile() を調査し、特にグローバルな markfilelist フィルターを確認してください。バンドルされているコードを upstream のコミット 8af0f098c3a42a28661d0295364e6e0fd7dbc92c と比較してください。脆弱な補間が upstream の安全な形式に置き換えられ、更新された Vim ソースが MacVim に統合されれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- macos, vim
- 領域
- desktop, security
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 静か
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 58/100