]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0421: vimball: can smuggle Vimscript into VimballRecord file v9.2.0421
authorChristian Brabandt <cb@256bit.org>
Wed, 29 Apr 2026 20:36:14 +0000 (20:36 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 29 Apr 2026 20:36:14 +0000 (20:36 +0000)
Problem:  vimball: can smuggle Vimscript into VimballRecord file
          (Mayank Jangid and Kushal Khemka)
Solution: Disallow strange file names

Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/autoload/vimball.vim
src/testdir/test_plugin_vimball.vim
src/version.c

index 8cc206f1d48b24c5fa656d1f46cdc82868d6bd02..3afd8e6c08e6551617461d93cc1facbdcafa392a 100644 (file)
@@ -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").": "
 
index ab740d1d2bb09888a0965bd207b292c24adf4343..30093ef719c02138941062d19861c0e824063e4b 100644 (file)
@@ -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('\n')[-1]
+  call assert_match('(Vimball) Forbidding strange filename:.* aborting\.\.\.', mess)
+  call s:teardown()
+endfunc
index 699db3c560cde8ea6bcd031b4a1596dd494cab5a..11ae9897aa49b4f3cffb28647da6439ad30bae1d 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    421,
 /**/
     420,
 /**/