]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0280: [security]: path traversal issue in zip.vim v9.2.0280
authorChristian Brabandt <cb@256bit.org>
Wed, 1 Apr 2026 16:23:49 +0000 (16:23 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 1 Apr 2026 16:23:49 +0000 (16:23 +0000)
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

Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/autoload/zip.vim
src/testdir/samples/evil.zip
src/testdir/test_plugin_zip.vim
src/version.c

index e81308fac1a79aa8465c4f388cc124bee1aa70b9..1ce9cfc2f75c15eaddd2a0bd16aba564240d7866 100644 (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
index e0a7f96141eed3ec5de68babd9d8bef7c72e5845..17cffadf934580090ebe2b3d3876edec14767658 100644 (file)
Binary files a/src/testdir/samples/evil.zip and b/src/testdir/samples/evil.zip differ
index 08f8223b60a649511f149dd811f0ac5495fa9cf1..53b6120834fcce56f8644ed06777f6c5eb8ef9cc 100644 (file)
@@ -274,3 +274,25 @@ def g:Test_zip_fname_evil_path()
   assert_match('zipfile://.*::etc/ax-pwn', @%)
   bw
 enddef
+
+def g:Test_zip_fname_evil_path2()
+  CheckNotMSWindows
+  # needed for writing the zip file
+  CheckExecutable zip
+
+  CopyZipFile("evil.zip")
+  defer delete("X.zip")
+  e X.zip
+
+  :1
+  var fname = 'foobar'
+  search('\V' .. fname)
+  exe "normal \<cr>"
+  normal x
+  assert_false(filereadable('/tmp/foobar'))
+  :w
+  var mess  = execute(':mess')
+  assert_match('Path Traversal Attack', mess)
+  assert_match('zipfile://.*::.*tmp/foobar', @%)
+  bw!
+enddef
index 43fee673fb6eab0f4937329fa02ea2bf365bde91..2c47f0d722eeaca8612ae6ba18213c09325184d0 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    280,
 /**/
     279,
 /**/