" vimball.vim : construct a file containing both paths and files
" Maintainer: This runtime file is looking for a new maintainer.
" Original Author: Charles E. Campbell
-" Date: Apr 11, 2016
+" Date: Apr 16, 2026
" Version: 37 (with modifications from the Vim Project)
" GetLatestVimScripts: 1502 1 :AutoInstall: vimball.vim
" Last Change:
-" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
-" 2026 Apr 05 by Vim Project: Detect path traversal attacks
-" 2026 Apr 09 by Vim Project: Detect more path traversal attacks
" Copyright: (c) 2004-2011 by Charles E. Campbell
" The VIM LICENSE applies to Vimball.vim, and Vimball.txt
" (see |copyright|) except use "Vimball" instead of "Vim".
let fsize = substitute(getline(linenr+1),'^\(\d\+\).\{-}$','\1','')+0
let fenc = substitute(getline(linenr+1),'^\d\+\s*\(\S\{-}\)$','\1','')
let filecnt = filecnt + 1
- " Do not allow a leading / or .. anywhere in the file name
- if fname =~ '\.\.' || fname =~ '^/'
+ " Do not allow a leading /, .. anywhere, or a Windows drive letter
+ " (e.g. C:/foo) in the file name. Backslashes were already converted
+ " to forward slashes above, so this also catches \\server\share UNC
+ " paths via the leading-slash check.
+ if fname =~ '\.\.' || fname =~ '^/' || fname =~ '^\a:'
echomsg "(Vimball) Path Traversal Attack detected, aborting..."
exe "tabn ".curtabnr
bw! Vimball
-*pi_vimball.txt* For Vim version 9.2. Last change: 2026 Apr 05
+*pi_vimball.txt* For Vim version 9.2. Last change: 2026 Apr 16
----------------
Vimball Archiver
==============================================================================
4. Vimball History *vimball-history* {{{1
+ unreleased:
+ Feb 28, 2025 * add support for bzip3 (#16755)
+ Apr 05, 2026 * Detect path traversal attacks
+ Apr 09, 2026 * Detect more path traversal attacks
+ Apr 16, 2026 * Block Windows drive letter paths
37 : Jul 18, 2014 * (by request of T. Miedema) added augroup around
the autocmds in vimballPlugin.vim
Jul 06, 2015 * there are two uses of tabc; changed to tabc!
call assert_false(filereadable('../XVimball/Xtest.txt'))
call s:teardown()
endfunc
+
+func Test_vimball_path_traversal_drive_letter()
+ call s:Mkvimball()
+ call delete('XVimball', 'rf')
+ sp Xtest.vmb
+ " try to write to a Windows-style absolute path with a drive letter
+ 4s#XVimball#C:/&#
+ so %
+ call feedkeys("\<cr>", "it")
+
+ let mess = execute(':mess')->split('\n')[-1]
+ call assert_match('(Vimball) Path Traversal Attack detected, aborting\.\.\.', mess)
+ call s:teardown()
+endfunc