vim-patch:9.2.0299: runtime(zip): may write using absolute paths (#38810)

Problem:  runtime(zip): may write using absolute paths
          (syndicate)
Solution: Detect this case and abort on Unix, warn in the documentation
          about possible issues

46f530e517

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 4aa8969d29)
This commit is contained in:
zeertzjq
2026-04-06 10:15:19 +08:00
committed by github-actions[bot]
parent f92a68d4bc
commit bf084967d7
4 changed files with 31 additions and 0 deletions

View File

@@ -21,6 +21,7 @@
" 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,
@@ -395,9 +396,16 @@ fun! zip#Write(fname)
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)

View File

@@ -33,6 +33,10 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright*
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

Binary file not shown.

View File

@@ -297,3 +297,22 @@ func Test_zip_fname_evil_path2()
call assert_match('zipfile://.*::.*tmp/foobar', @%)
bw!
endfunc
func Test_zip_fname_evil_path3()
CheckNotMSWindows
" needed for writing the zip file
CheckExecutable zip
call s:CopyZipFile("evil.zip")
defer delete("X.zip")
e X.zip
:1
let fname = 'payload.txt'
call search('\V' .. fname)
exe "normal \<cr>"
:w!
let mess = execute(':mess')
call assert_match('Path Traversal Attack', mess)
bw!
endfunc