runtime: don't execute external commands when loading ftplugins
This is a followup to 816fbcc262687b81fc46f82f7bbeb1453addfe0c (patch
9.0.1833: [security] runtime file fixes)
It basically disables that external commands are run on loading of the
filetype plugin, **unless** the user has set the `g:plugin_exec = 1`
global variable in their configuration or for a specific filetype the
variable g:<filetype>_exec=1.
There are a few more plugins, that may execute system commands like
debchangelog, gitcommit, sh, racket, zsh, ps1 but those do at least
do not run those commands by default during loading of the filetype plugin
(there the command is mostly run as convenience for auto-completion or
to provide documentation lookup).
closes: #13034
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Tim Pope <vim@tpope.org>
diff --git a/runtime/ftplugin/awk.vim b/runtime/ftplugin/awk.vim
index 1bca3ad..785088f 100644
--- a/runtime/ftplugin/awk.vim
+++ b/runtime/ftplugin/awk.vim
@@ -37,11 +37,14 @@
let b:undo_ftplugin .= " | setl fp<"
endif
- let path = system("gawk 'BEGIN { printf ENVIRON[\"AWKPATH\"] }'")
- let path = substitute(path, '^\.\=:\|:\.\=$\|:\.\=:', ',,', 'g') " POSIX cwd
- let path = substitute(path, ':', ',', 'g')
+ " Disabled by default for security reasons.
+ if get(g:, 'awk_exec', get(g:, 'plugin_exec', 0))
+ let path = system("gawk 'BEGIN { printf ENVIRON[\"AWKPATH\"] }'")
+ let path = substitute(path, '^\.\=:\|:\.\=$\|:\.\=:', ',,', 'g') " POSIX cwd
+ let path = substitute(path, ':', ',', 'g')
- let &l:path = path
+ let &l:path = path
+ endif
let b:undo_ftplugin .= " | setl inc< path<"
endif
diff --git a/runtime/ftplugin/changelog.vim b/runtime/ftplugin/changelog.vim
index e9df63f..a624333 100644
--- a/runtime/ftplugin/changelog.vim
+++ b/runtime/ftplugin/changelog.vim
@@ -55,13 +55,19 @@
elseif $EMAIL_ADDRESS != ""
return $EMAIL_ADDRESS
endif
+ let s:default_login = 'unknown'
- let login = s:login()
+ " Disabled by default for security reasons.
+ if get(g:, 'changelog_exec', get(g:, 'plugin_exec', 0))
+ let login = s:login()
+ else
+ let login = s:default_login
+ endif
return printf('%s <%s@%s>', s:name(login), login, s:hostname())
endfunction
function! s:login()
- return s:trimmed_system_with_default('whoami', 'unknown')
+ return s:trimmed_system_with_default('whoami', s:default_login)
endfunction
function! s:trimmed_system_with_default(command, default)
@@ -71,7 +77,7 @@
function! s:system_with_default(command, default)
let output = system(a:command)
if v:shell_error
- return default
+ return a:default
endif
return output
endfunction
diff --git a/runtime/ftplugin/perl.vim b/runtime/ftplugin/perl.vim
index 4361097..f3de81d 100644
--- a/runtime/ftplugin/perl.vim
+++ b/runtime/ftplugin/perl.vim
@@ -54,10 +54,12 @@
" Set this once, globally.
if !exists("perlpath")
- " safety check: don't execute perl from current directory
let s:tmp_cwd = getcwd()
- if executable("perl") && (fnamemodify(exepath("perl"), ":p:h") != s:tmp_cwd
- \ || (index(split($PATH,has("win32")? ';' : ':'), s:tmp_cwd) != -1 && s:tmp_cwd != '.'))
+ " safety check: don't execute perl binary by default
+ if executable("perl") && get(g:, 'perl_exec', get(g:, 'plugin_exec', 0))
+ \ && (fnamemodify(exepath("perl"), ":p:h") != s:tmp_cwd
+ \ || (index(split($PATH, has("win32") ? ';' : ':'), s:tmp_cwd) != -1
+ \ && s:tmp_cwd != '.'))
try
if &shellxquote != '"'
let perlpath = system('perl -e "print join(q/,/,@INC)"')
@@ -73,7 +75,7 @@
" current directory and the directory of the current file.
let perlpath = ".,,"
endif
- unlet s:tmp_cwd
+ unlet! s:tmp_cwd
endif
" Append perlpath to the existing path value, if it is set. Since we don't
diff --git a/runtime/ftplugin/ruby.vim b/runtime/ftplugin/ruby.vim
index a424801..b61c176 100644
--- a/runtime/ftplugin/ruby.vim
+++ b/runtime/ftplugin/ruby.vim
@@ -61,6 +61,10 @@
endif
function! s:query_path(root) abort
+ " Disabled by default for security reasons.
+ if !get(g:, 'ruby_exec', get(g:, 'plugin_exec', 0))
+ return []
+ endif
let code = "print $:.join %q{,}"
if &shell =~# 'sh' && empty(&shellxquote)
let prefix = 'env PATH='.shellescape($PATH).' '
@@ -84,7 +88,7 @@
else
let path = split(system(path_check),',')
endif
- unlet s:tmp_cwd
+ unlet! s:tmp_cwd
exe cd cwd
return path
finally
diff --git a/runtime/ftplugin/zig.vim b/runtime/ftplugin/zig.vim
index 45ea582..2a08198 100644
--- a/runtime/ftplugin/zig.vim
+++ b/runtime/ftplugin/zig.vim
@@ -40,17 +40,17 @@
let &l:define='\v(<fn>|<const>|<var>|^\s*\#\s*define)'
" Safety check: don't execute zip from current directory
-let s:tmp_cwd = getcwd()
if !exists('g:zig_std_dir') && exists('*json_decode') &&
- \ executable('zig') && (fnamemodify(exepath("zig"), ":p:h") != s:tmp_cwd
- \ || (index(split($PATH,has("win32")? ';' : ':'), s:tmp_cwd) != -1 && s:tmp_cwd != '.'))
+ \ executable('zig') && get(g:, 'zig_exec', get(g:, 'plugin_exec', 0))
+ \ && (fnamemodify(exepath("zig"), ":p:h") != s:tmp_cwd
+ \ || (index(split($PATH,has("win32")? ';' : ':'), s:tmp_cwd) != -1 && s:tmp_cwd != '.'))
silent let s:env = system('zig env')
if v:shell_error == 0
let g:zig_std_dir = json_decode(s:env)['std_dir']
endif
unlet! s:env
endif
-unlet s:tmp_cwd
+unlet! s:tmp_cwd
if exists('g:zig_std_dir')
let &l:path = &l:path . ',' . g:zig_std_dir