From: Christian Brabandt Date: Wed, 29 Apr 2026 20:36:14 +0000 (+0000) Subject: patch 9.2.0421: vimball: can smuggle Vimscript into VimballRecord file X-Git-Tag: v9.2.0421^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=77499e009af677720e747debebedb78d12a77cb6;p=thirdparty%2Fvim.git 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 --- diff --git a/runtime/autoload/vimball.vim b/runtime/autoload/vimball.vim index 8cc206f1d4..3afd8e6c08 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 ab740d1d2b..30093ef719 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("\", "it") + + let mess = execute(':mess')->split('\n')[-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 699db3c560..11ae9897aa 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, /**/