vim-patch:9.2.0280: [security]: path traversal issue in zip.vim (#38693)

Problem:  [security]: path traversal issue in zip.vim
          (Michał Majchrowicz)
Solution: Detect more such attacks and warn the user.

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-jc86-w7vm-8p24

7088926316

Co-authored-by: Christian Brabandt <cb@256bit.org>
(cherry picked from commit 0851ac2706)
This commit is contained in:
zeertzjq
2026-04-02 06:23:23 +08:00
committed by github-actions[bot]
parent 0142453543
commit 3e2ce64f88
3 changed files with 29 additions and 1 deletions

View File

@@ -20,6 +20,7 @@
" 2025 Dec 20 by Vim Project: use :lcd instead of :cd
" 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
" 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,
@@ -367,6 +368,11 @@ fun! zip#Write(fname)
return
endif
if simplify(a:fname) =~ '\.\.[/\\]'
call s:Mess('Error', "***error*** (zip#Write) Path Traversal Attack detected, not writing!")
return
endif
let curdir= getcwd()
let tmpdir= tempname()
if tmpdir =~ '\.'
@@ -481,7 +487,7 @@ fun! zip#Extract()
if fname =~ '/$'
call s:Mess('Error', "***error*** (zip#Extract) Please specify a file, not a directory")
return
elseif fname =~ '^[.]\?[.]/'
elseif fname =~ '^[.]\?[.]/' || simplify(fname) =~ '\.\.[/\\]'
call s:Mess('Error', "***error*** (zip#Browse) Path Traversal Attack detected, not extracting!")
return
endif

Binary file not shown.

View File

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