]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0276: [security]: modeline security bypass v9.2.0276
authorChristian Brabandt <cb@256bit.org>
Tue, 31 Mar 2026 18:29:00 +0000 (18:29 +0000)
committerChristian Brabandt <cb@256bit.org>
Tue, 31 Mar 2026 18:29:00 +0000 (18:29 +0000)
Problem:  [security]: modeline security bypass
Solution: disallow mapset() from secure mode, set the P_MLE flag for the
          'complete', 'guitabtooltip' and 'printheader' options.

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-8h6p-m6gr-mpw9

Signed-off-by: Christian Brabandt <cb@256bit.org>
src/map.c
src/optiondefs.h
src/testdir/test_modeline.vim
src/version.c

index 0a909fb93b2e453be56375f7c6af62fc8da2f098..5f07ef4a81433154d56729768fc7206a3b559765 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -2746,6 +2746,9 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
     int                dict_only;
     mapblock_T *mp_result[2] = {NULL, NULL};
 
+    if (check_secure())
+       return;
+
     // If first arg is a dict, then that's the only arg permitted.
     dict_only = argvars[0].v_type == VAR_DICT;
     if (in_vim9script()
index ca2795a364b665858a7d5581031be2cf73b41e4b..a6f83830842851ed08bbef997b7c13dd604fb398 100644 (file)
@@ -681,7 +681,7 @@ static struct vimoption options[] =
     {"compatible",  "cp",   P_BOOL|P_RALL,
                            (char_u *)&p_cp, PV_NONE, did_set_compatible, NULL,
                            {(char_u *)TRUE, (char_u *)FALSE} SCTX_INIT},
-    {"complete",    "cpt",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
+    {"complete",    "cpt",  P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP|P_MLE,
                            (char_u *)&p_cpt, PV_CPT, did_set_complete, expand_set_complete,
                            {(char_u *)".,w,b,u,t,i", (char_u *)0L}
                            SCTX_INIT},
@@ -1324,7 +1324,7 @@ static struct vimoption options[] =
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
-    {"guitabtooltip",  "gtt", P_STRING|P_VI_DEF|P_RWIN,
+    {"guitabtooltip",  "gtt", P_STRING|P_VI_DEF|P_RWIN|P_MLE,
 #if defined(FEAT_GUI_TABLINE)
                            (char_u *)&p_gtt, PV_NONE, NULL, NULL,
                            {(char_u *)"", (char_u *)0L}
@@ -2041,7 +2041,7 @@ static struct vimoption options[] =
                            {(char_u *)NULL, (char_u *)0L}
 #endif
                            SCTX_INIT},
-    {"printheader", "pheader",  P_STRING|P_VI_DEF|P_GETTEXT,
+    {"printheader", "pheader",  P_STRING|P_VI_DEF|P_GETTEXT|P_MLE,
 #ifdef FEAT_PRINTER
                            (char_u *)&p_header, PV_NONE, NULL, NULL,
                            // untranslated to avoid problems when 'encoding'
index 4cc091b9ca586c606e68c8de690da4512f3653fc..25ca6fb437003179e5b923c4e55d4034e20e4655 100644 (file)
@@ -490,4 +490,29 @@ func Test_modeline_nowrap_lcs_extends()
   set equalalways&
 endfunc
 
+func Test_modeline_forbidden()
+  let tempfile = tempname()
+  let lines =<< trim END
+    some test text for completion
+    vim: set complete=F{->system('touch_should_not_run')} :
+  END
+  call writefile(lines, tempfile, 'D')
+  call assert_fails($'new {tempfile}', 'E992:')
+  bw!
+  let lines =<< trim END
+    some text
+    vim: set guitabtooltip=%{%mapset()%}:
+  END
+  call writefile(lines, tempfile)
+  call assert_fails($'new {tempfile}', 'E992:')
+  bw!
+  let lines =<< trim END
+    some text
+    vim: set printheader=%{mapset('n',0,{})%)%}:
+  END
+  call writefile(lines, tempfile, 'D')
+  call assert_fails($'new {tempfile}', 'E992:')
+  bw!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 3fa39ae403558a29990829768fa4fa21edc69eba..708522164cf83dc9c080c85e298055ad7983adf8 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    276,
 /**/
     275,
 /**/