" 2026 Feb 08 by Vim Project: use system() instead of :!
" 2026 Mar 08 by Vim Project: Make ZipUpdatePS() check for powershell
" 2026 Apr 01 by Vim Project: Detect more path traversal attacks
+" 2026 Apr 05 by Vim Project: Detect more path traversal attacks
" License: Vim License (see vim's :help license)
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
if has("unix")
let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','')
let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','')
+ " fname should not start with a leading slash to avoid writing anywhere into the system
+ if fname =~ '^/'
+ call s:Mess('Error', "***error*** (zip#Write) Path Traversal Attack detected, not writing!")
+ call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
+ return
+ endif
else
let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
+ " TODO: what to check on MS-Windows to avoid writing absolute paths?
endif
if fname =~ '^[.]\{1,2}/'
let gnu_cmd = g:zip_zipcmd . ' -d ' . s:Escape(fnamemodify(zipfile,":p"),0) . ' ' . s:Escape(fname,0)
-*pi_zip.txt* For Vim version 9.2. Last change: 2026 Feb 14
+*pi_zip.txt* For Vim version 9.2. Last change: 2026 Apr 05
+====================+
| Zip File Interface |
also write to the file. Currently, one may not make a new file in
zip archives via the plugin.
+ The zip plugin tries to detect some common path traversal attack
+ patterns, but it may not catch all possible cases. Please be very
+ careful when using this plugin with untrusted input.
+
COMMANDS~
*zip-x*
x : extract a listed file when the cursor is atop it
assert_match('zipfile://.*::.*tmp/foobar', @%)
bw!
enddef
+
+def g:Test_zip_fname_evil_path3()
+ CheckNotMSWindows
+ # needed for writing the zip file
+ CheckExecutable zip
+
+ CopyZipFile("evil.zip")
+ defer delete("X.zip")
+ e X.zip
+
+ :1
+ var fname = 'payload.txt'
+ search('\V' .. fname)
+ exe "normal \<cr>"
+ :w!
+ var mess = execute(':mess')
+ assert_match('Path Traversal Attack', mess)
+ bw!
+enddef