Skip to content

Commit 46f530e

Browse files
committed
patch 9.2.0299: runtime(zip): may write using absolute paths
Problem: runtime(zip): may write using absolute paths (syndicate) Solution: Detect this case and abort on Unix, warn in the documentation about possible issues Signed-off-by: Christian Brabandt <[email protected]>
1 parent 5943c57 commit 46f530e

5 files changed

Lines changed: 34 additions & 1 deletion

File tree

runtime/autoload/zip.vim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
" 2026 Feb 08 by Vim Project: use system() instead of :!
2222
" 2026 Mar 08 by Vim Project: Make ZipUpdatePS() check for powershell
2323
" 2026 Apr 01 by Vim Project: Detect more path traversal attacks
24+
" 2026 Apr 05 by Vim Project: Detect more path traversal attacks
2425
" License: Vim License (see vim's :help license)
2526
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
2627
" Permission is hereby granted to use and distribute this code,
@@ -395,9 +396,16 @@ fun! zip#Write(fname)
395396
if has("unix")
396397
let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','')
397398
let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','')
399+
" fname should not start with a leading slash to avoid writing anywhere into the system
400+
if fname =~ '^/'
401+
call s:Mess('Error', "***error*** (zip#Write) Path Traversal Attack detected, not writing!")
402+
call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
403+
return
404+
endif
398405
else
399406
let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
400407
let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
408+
" TODO: what to check on MS-Windows to avoid writing absolute paths?
401409
endif
402410
if fname =~ '^[.]\{1,2}/'
403411
let gnu_cmd = g:zip_zipcmd . ' -d ' . s:Escape(fnamemodify(zipfile,":p"),0) . ' ' . s:Escape(fname,0)

runtime/doc/pi_zip.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*pi_zip.txt* For Vim version 9.2. Last change: 2026 Feb 14
1+
*pi_zip.txt* For Vim version 9.2. Last change: 2026 Apr 05
22

33
+====================+
44
| Zip File Interface |
@@ -33,6 +33,10 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright*
3333
also write to the file. Currently, one may not make a new file in
3434
zip archives via the plugin.
3535

36+
The zip plugin tries to detect some common path traversal attack
37+
patterns, but it may not catch all possible cases. Please be very
38+
careful when using this plugin with untrusted input.
39+
3640
COMMANDS~
3741
*zip-x*
3842
x : extract a listed file when the cursor is atop it

src/testdir/samples/evil.zip

149 Bytes
Binary file not shown.

src/testdir/test_plugin_zip.vim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,22 @@ def g:Test_zip_fname_evil_path2()
296296
assert_match('zipfile://.*::.*tmp/foobar', @%)
297297
bw!
298298
enddef
299+
300+
def g:Test_zip_fname_evil_path3()
301+
CheckNotMSWindows
302+
# needed for writing the zip file
303+
CheckExecutable zip
304+
305+
CopyZipFile("evil.zip")
306+
defer delete("X.zip")
307+
e X.zip
308+
309+
:1
310+
var fname = 'payload.txt'
311+
search('\V' .. fname)
312+
exe "normal \<cr>"
313+
:w!
314+
var mess = execute(':mess')
315+
assert_match('Path Traversal Attack', mess)
316+
bw!
317+
enddef

src/version.c

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

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
299,
737739
/**/
738740
298,
739741
/**/

0 commit comments

Comments
 (0)