patch 9.2.0421: vimball: can smuggle Vimscript into VimballRecord file

Commit: 
https://github.com/vim/vim/commit/77499e009af677720e747debebedb78d12a77cb6
Author: Christian Brabandt <[email protected]>
Date:   Wed Apr 29 20:36:14 2026 +0000

    patch 9.2.0421: vimball: can smuggle Vimscript into VimballRecord file
    
    Problem:  vimball: can smuggle Vimscript into VimballRecord file
              (Mayank Jangid and Kushal Khemka)
    Solution: Disallow strange file names
    
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/autoload/vimball.vim b/runtime/autoload/vimball.vim
index 8cc206f1d..3afd8e6c0 100644
--- a/runtime/autoload/vimball.vim
+++ b/runtime/autoload/vimball.vim
@@ -103,14 +103,14 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range
 
   while linenr <= a:line2
    let svfile  = getline(linenr)
- 
+
    if !filereadable(svfile)
     call vimball#ShowMesg(s:ERROR,"unable to read file<".svfile.">")
     call s:ChgDir(curdir)
     call vimball#RestoreSettings()
     return
    endif
- 
+
    " create/switch to mkvimball tab
    if !exists("vbtabnr")
     tabnew
@@ -119,7 +119,7 @@ fun! vimball#MkVimball(line1,line2,writelevel,...) range
    else
     exe "tabn ".vbtabnr
    endif
- 
+
    let lastline= line("$") + 1
    if lastline == 2 && getline("$") == ""
     call setline(1,'" Vimball Archiver by Charles E. Campbell')
@@ -163,7 +163,7 @@ endfun
 
 " ---------------------------------------------------------------------
 " vimball#Vimball: extract and distribute contents from a vimball {{{2
-"                  (invoked the the UseVimball command embedded in 
+"                  (invoked the the UseVimball command embedded in
 "                  vimballs' prologue)
 fun! vimball#Vimball(really,...)
 
@@ -213,7 +213,7 @@ fun! vimball#Vimball(really,...)
   " give title to listing of (extracted) files from Vimball Archive
   if a:really
    echohl Title     | echomsg "Vimball Archive"         | echohl None
-  else             
+  else
    echohl Title     | echomsg "Vimball Archive Listing" | echohl None
    echohl Statement | echomsg "files would be placed under: ".home | echohl 
None
   endif
@@ -237,6 +237,15 @@ fun! vimball#Vimball(really,...)
      bw! Vimball
      call s:ChgDir(curdir)
      return
+   " Also, disallow strange paths, that could lead to code execution from
+   " .VimballRecord
+   " Disallow: pipe, quotes and closing paren
+   elseif fname =~ '[|'')"]'
+     echomsg printf("(Vimball) Forbidding strange filename: '%s', 
aborting...", fname)
+     exe "tabn ".curtabnr
+     bw! Vimball
+     call s:ChgDir(curdir)
+     return
    endif
 
    if a:really
@@ -295,7 +304,7 @@ fun! vimball#Vimball(really,...)
       exe "silent w! ".fnameescape(fnamepath)
     endif
     echo "wrote ".fnameescape(fnamepath)
-    call s:RecordInVar(home,"call delete('".fnamepath."')")
+    call s:RecordInVar(home,"call delete('".escape(fnamepath, '"''|')."')")
     endif
 
     " return to tab with vimball
@@ -370,7 +379,7 @@ fun! vimball#RmVimball(...)
 
   call s:ChgDir(home)
   if filereadable(".VimballRecord")
-   keepalt keepjumps 1split 
+   keepalt keepjumps 1split
    sil! keepalt keepjumps e .VimballRecord
    let keepsrch= @/
    if search('^\M'.curfile."\m: ".'cw')
@@ -558,7 +567,7 @@ fun! s:RecordInFile(home)
   if exists("s:recordfile") || exists("s:recorddir")
    let curdir= getcwd()
    call s:ChgDir(a:home)
-   keepalt keepjumps 1split 
+   keepalt keepjumps 1split
 
    let cmd= expand("%:tr").": "
 
diff --git a/src/testdir/test_plugin_vimball.vim 
b/src/testdir/test_plugin_vimball.vim
index ab740d1d2..30093ef71 100644
--- a/src/testdir/test_plugin_vimball.vim
+++ b/src/testdir/test_plugin_vimball.vim
@@ -97,3 +97,16 @@ func Test_vimball_path_traversal_drive_letter()
   call assert_match('(Vimball) Path Traversal Attack detected, 
aborting\.\.\.', mess)
   call s:teardown()
 endfunc
+
+func Test_vimball_evil_filenames()
+  call s:Mkvimball()
+  call delete('XVimball', 'rf')
+  sp Xtest.vmb
+  4s#XVimball#pwn')#
+  so %
+  call feedkeys("\<cr>", "it")
+
+  let mess = execute(':mess')->split('
')[-1]
+  call assert_match('(Vimball) Forbidding strange filename:.* aborting\.\.\.', 
mess)
+  call s:teardown()
+endfunc
diff --git a/src/version.c b/src/version.c
index 699db3c56..11ae9897a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    421,
 /**/
     420,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1wIBmK-007rMx-1l%40256bit.org.

Raspunde prin e-mail lui