From 75661a66a1db1e1f3f1245c615f13a7de44c0587 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Tue, 31 Mar 2026 18:29:00 +0000 Subject: [PATCH] patch 9.2.0276: [security]: modeline security bypass 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 Backported for vim 9.1.083 --- src/map.c | 3 +++ src/optiondefs.h | 6 +++--- src/testdir/test_modeline.vim | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/map.c b/src/map.c index 0a909fb93b2e4..5f07ef4a81433 100644 --- a/src/map.c +++ b/src/map.c @@ -2708,6 +2708,9 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED) char_u *arg; int dict_only; + 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() diff --git a/src/optiondefs.h b/src/optiondefs.h index ca2795a364b66..a6f8383084285 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -639,7 +639,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}, @@ -1251,7 +1251,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} @@ -1950,7 +1950,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' diff --git a/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim index 4cc091b9ca586..25ca6fb437003 100644 --- a/src/testdir/test_modeline.vim +++ b/src/testdir/test_modeline.vim @@ -469,4 +469,29 @@ func Test_modeline_disable() call assert_equal(2, &sw) 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 -- 2.53.0