rc modeline: Prevent command execution

This commit prevents specially crafted modelines from making the
editor execute arbitrary Kakoune commands.

By using a tabulation character as a separator, commands can be
injected in the value of the options listed in the modeline. For
example:

	# kak: tabstop=2;set-option	buffer	pwned	yes

Fixes #3735.
This commit is contained in:
Frank LENORMAND 2020-09-16 11:37:01 +03:00
parent dbd7e4da79
commit 6976b1dce4

View File

@ -12,6 +12,8 @@ declare-option -docstring "amount of lines that will be checked at the beginning
define-command -hidden modeline-parse-impl %{ define-command -hidden modeline-parse-impl %{
evaluate-commands %sh{ evaluate-commands %sh{
kakquote() { printf "%s" "$*" | sed "s/'/''/g; 1s/^/'/; \$s/\$/'/"; }
# Translate a vim option into the corresponding kakoune one # Translate a vim option into the corresponding kakoune one
translate_opt_vim() { translate_opt_vim() {
readonly key="$1" readonly key="$1"
@ -19,11 +21,11 @@ define-command -hidden modeline-parse-impl %{
tr="" tr=""
case "${key}" in case "${key}" in
so|scrolloff) tr="scrolloff ${value},${kak_opt_scrolloff##*,}";; so|scrolloff) tr=$(kakquote scrolloff "${value},${kak_opt_scrolloff##*,}");;
siso|sidescrolloff) tr="scrolloff ${kak_opt_scrolloff%%,*},${value}";; siso|sidescrolloff) tr=$(kakquote scrolloff "${kak_opt_scrolloff%%,*},${value}");;
ts|tabstop) tr="tabstop ${value}";; ts|tabstop) tr=$(kakquote tabstop "${value}");;
sw|shiftwidth) tr="indentwidth ${value}";; sw|shiftwidth) tr=$(kakquote indentwidth "${value}");;
tw|textwidth) tr="autowrap_column ${value}";; tw|textwidth) tr=$(kakquote autowrap_column "${value}");;
ff|fileformat) ff|fileformat)
case "${value}" in case "${value}" in
unix) tr="eolformat lf";; unix) tr="eolformat lf";;
@ -31,10 +33,10 @@ define-command -hidden modeline-parse-impl %{
*) printf %s\\n "echo -debug 'Unsupported file format: ${value}'";; *) printf %s\\n "echo -debug 'Unsupported file format: ${value}'";;
esac esac
;; ;;
ft|filetype) tr="filetype ${value}";; ft|filetype) tr=$(kakquote filetype "{value}");;
bomb) tr="BOM utf8";; bomb) tr="BOM utf8";;
nobomb) tr="BOM none";; nobomb) tr="BOM none";;
spelllang|spl) tr="spell_lang ${value%%,*}";; spelllang|spl) tr=$(kakquote spell_lang "{value%%,*}");;
*) printf %s\\n "echo -debug 'Unsupported vim variable: ${key}'";; *) printf %s\\n "echo -debug 'Unsupported vim variable: ${key}'";;
esac esac
@ -52,7 +54,7 @@ define-command -hidden modeline-parse-impl %{
return;; return;;
esac esac
printf %s\\n "set-option buffer ${key} ${value}" printf 'set-option buffer %s' "$(kakquote "${key}" "${value}")"
} }
case "${kak_selection}" in case "${kak_selection}" in