Skip to content

Commit 334a13b

Browse files
committed
patch 9.1.1164: [security]: code execution with tar.vim and special crafted tar files
Problem: editing a special crafted tar file allows code execution (RyotaK, after 129a844) Solution: escape the filename before feeding it to the `:read` command Github Advisory: GHSA-wfmf-8626-q3r3 Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 8872012 commit 334a13b

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

runtime/autoload/tar.vim

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
" 2025 Feb 06 by Vim Project: add support for lz4 (#16591)
1212
" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
1313
" 2025 Mar 01 by Vim Project: fix syntax error in tar#Read()
14+
" 2025 Mar 02 by Vim Project: escape the filename before using :read
1415
"
1516
" Contains many ideas from Michael Toren's <tar.vim>
1617
"
@@ -284,6 +285,8 @@ fun! tar#Read(fname,mode)
284285
set report=10
285286
let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
286287
let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
288+
" be careful not to execute special crafted files
289+
let escape_file = fname->fnameescape()
287290

288291
" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact
289292
if !exists("*mkdir")
@@ -361,13 +364,13 @@ fun! tar#Read(fname,mode)
361364

362365
if tarfile =~# '\.bz2$'
363366
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
364-
exe "read ".fname
367+
exe "read ".escape_file
365368
elseif tarfile =~# '\.bz3$'
366369
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
367-
exe "read ".fname
370+
exe "read ".escape_file
368371
elseif tarfile =~# '\.\(gz\)$'
369372
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
370-
exe "read ".fname
373+
exe "read ".escape_file
371374
elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)'
372375
if has("unix") && executable("file")
373376
let filekind= system("file ".shellescape(tarfile,1))
@@ -376,40 +379,40 @@ fun! tar#Read(fname,mode)
376379
endif
377380
if filekind =~ "bzip2"
378381
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
379-
exe "read ".fname
382+
exe "read ".escape_file
380383
elseif filekind =~ "bzip3"
381384
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
382-
exe "read ".fname
385+
exe "read ".escape_file
383386
elseif filekind =~ "XZ"
384387
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
385-
exe "read ".fname
388+
exe "read ".escape_file
386389
elseif filekind =~ "Zstandard"
387390
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
388-
exe "read ".fname
391+
exe "read ".escape_file
389392
else
390393
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
391-
exe "read ".fname
394+
exe "read ".escape_file
392395
endif
393396

394397
elseif tarfile =~# '\.lrp$'
395398
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
396-
exe "read ".fname
399+
exe "read ".escape_file
397400
elseif tarfile =~# '\.lzma$'
398401
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
399-
exe "read ".fname
402+
exe "read ".escape_file
400403
elseif tarfile =~# '\.\(xz\|txz\)$'
401404
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
402-
exe "read ".fname
405+
exe "read ".escape_file
403406
elseif tarfile =~# '\.\(lz4\|tlz4\)$'
404407
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
405-
exe "read ".fname
408+
exe "read ".escape_file
406409
else
407410
if tarfile =~ '^\s*-'
408411
" A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
409412
let tarfile = substitute(tarfile, '-', './-', '')
410413
endif
411414
exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp
412-
exe "read ".fname
415+
exe "read ".escape_file
413416
endif
414417

415418
redraw!

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
1164,
707709
/**/
708710
1163,
709711
/**/

0 commit comments

Comments
 (0)