Commit: patch 9.2.0435: [security]: backticks in 'path' may cause shell execution on completion

11 views
Skip to first unread message

Christian Brabandt

unread,
May 3, 2026, 2:30:17 PMMay 3
to vim...@googlegroups.com
patch 9.2.0435: [security]: backticks in 'path' may cause shell execution on completion

Commit: https://github.com/vim/vim/commit/190cb3c2b9c769a3972bcfd991a7b5b6cb771ef0
Author: Christian Brabandt <c...@256bit.org>
Date: Sun May 3 16:10:03 2026 +0000

patch 9.2.0435: [security]: backticks in 'path' may cause shell execution on completion

Problem: [security]: Backticks enclosed shell commands in the 'path'
option value are executed during completion (q1uf3ng).
Solution: Skip path entries containing backticks, add P_SECURE to 'path'
option, so that it cannot be set from a modeline (for symmetry with
the 'cdpath' option)

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-hwg5-3cxw-wvvg

Supported by AI.

Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 7e1d4cb67..4628a1624 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt* For Vim version 9.2. Last change: 2026 May 01
+*options.txt* For Vim version 9.2. Last change: 2026 May 03


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -6799,6 +6799,9 @@ A jump table for the options with a short description can be found at |Q_op|.
< Replace the ';' with a ':' or whatever separator is used. Note that
this doesn't work when $INCL contains a comma or white space.

+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
+
*'perldll'*
'perldll' string (default depends on the build)
global
diff --git a/src/findfile.c b/src/findfile.c
index ed0ee76c4..af9523dcd 100644
--- a/src/findfile.c
+++ b/src/findfile.c
@@ -2412,6 +2412,10 @@ expand_path_option(
{
buflen = copy_option_part(&path_option, buf, MAXPATHL, " ,");

+ // do not expand backticks, could have been set via a modeline
+ if (vim_strchr(buf, '`') != NULL)
+ continue;
+
if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1])))
{
size_t plen;
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 0a93b70f8..f712ab7a1 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -1958,7 +1958,7 @@ static struct vimoption options[] =
(char_u *)&p_pm, PV_NONE,
did_set_backupext_or_patchmode, NULL,
{(char_u *)"", (char_u *)0L} SCTX_INIT},
- {"path", "pa", P_STRING|P_EXPAND|P_VI_DEF|P_COMMA|P_NODUP,
+ {"path", "pa", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE|P_COMMA|P_NODUP,
(char_u *)&p_path, PV_PATH, NULL, NULL,
{
#if defined(AMIGA) || defined(MSWIN)
diff --git a/src/testdir/test_find_complete.vim b/src/testdir/test_find_complete.vim
index 079fb7804..8b8b71c30 100644
--- a/src/testdir/test_find_complete.vim
+++ b/src/testdir/test_find_complete.vim
@@ -161,4 +161,21 @@ func Test_find_complete()
set path&
endfunc

+" Verify that backticks in 'path' are not executed
+func Test_find_completion_backtick_in_path()
+ CheckUnix
+ CheckExecutable id
+
+ new Xpoc.c
+ setl path+=`id>Xrce_marker`
+ " Triggering completion must not execute the backtick command.
+ call getcompletion('', 'file_in_path')
+ call assert_false(filereadable('Xrce_marker'))
+ call feedkeys(":find
", "xt")
+ call assert_false(filereadable('Xrce_marker'))
+
+ bwipe!
+ call delete('Xrce_marker')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim
index 6884ab473..6cbf87638 100644
--- a/src/testdir/test_modeline.vim
+++ b/src/testdir/test_modeline.vim
@@ -665,4 +665,18 @@ func Test_modeline_strict_cannot_be_set_from_modeline()
let &modeline = modeline
endfunc

+" Verify that backticks in 'path' set from a modeline are not executed
+func Test_path_modeline()
+ let lines =<< trim END
+ // vim: set path+=foobar :
+ END
+ call writefile(lines, 'Xpoc.c', 'D')
+
+ set nomodelinestrict modeline
+ call assert_fails('split Xpoc.c', 'E520:')
+
+ bwipe!
+ set modelinestrict& modeline&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 6d8157e4a..2691f438b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 435,
/**/
434,
/**/
Reply all
Reply to author
Forward
0 new messages