branch: elpa/flycheck
commit 79a599302a965d8cff554945db4fb470084a788d
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>
[Fix #2159] Properly mitigate CVE-2024-53920 on Emacs 30+
On Emacs 30+, disable the emacs-lisp checker for files not marked
as trusted via `trusted-content`. Byte-compilation triggers macro
expansion which can execute arbitrary code, so the previous
mitigation (disabling `enable-local-eval`) was insufficient.
---
CHANGES.rst | 6 ++++++
doc/languages.rst | 9 +++++++++
flycheck-buttercup.el | 15 +++++++++++----
flycheck.el | 21 ++++++++++++++++++++-
test/specs/languages/test-emacs-lisp.el | 19 +++++++++++++++++++
5 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/CHANGES.rst b/CHANGES.rst
index 518729b994..a5a3d50744 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -28,6 +28,12 @@
``LC_ALL=C``, so the character encoding is left untouched. ``LC_ALL=C``
broke checkers reading UTF-8 input, such as ``hledger``.
+- [#2159]: Properly mitigate CVE-2024-53920 in the ``emacs-lisp`` checker
+ by requiring files to be marked as trusted (via ``trusted-content``) on
+ Emacs 30+. Byte-compilation triggers macro expansion which can execute
+ arbitrary code, so the checker is now disabled for untrusted files.
+ ``emacs-lisp-checkdoc`` doesn't expand macros and stays enabled.
+
36.0 (2026-02-19)
======================
diff --git a/doc/languages.rst b/doc/languages.rst
index 58f3de6be2..b9eace5325 100644
--- a/doc/languages.rst
+++ b/doc/languages.rst
@@ -350,6 +350,15 @@ to view the docstring of the syntax checker. Likewise,
you may use
Check syntax with the built-in byte compiler.
+ On Emacs 30+, this checker is only enabled for files marked as
+ trusted via ``trusted-content`` (see :infonode:`(emacs)Safe File
+ Variables`), to mitigate CVE-2024-53920. Byte-compilation involves
+ macro expansion which can execute arbitrary code, so untrusted files
+ must not be byte-compiled. To use this checker, add your project
+ directories to ``trusted-content``. The ``emacs-lisp-checkdoc``
+ checker doesn't expand macros and remains enabled for untrusted
+ files.
+
.. defcustom:: flycheck-emacs-lisp-load-path
The load path as list of strings. Relative directories are expanded
diff --git a/flycheck-buttercup.el b/flycheck-buttercup.el
index 48ced63b37..01f5710bdf 100644
--- a/flycheck-buttercup.el
+++ b/flycheck-buttercup.el
@@ -253,15 +253,22 @@ with VALUE."
(setenv var value))
,@body))
+;; `trusted-content' only exists on Emacs 30+; declare it so that the
+;; let-binding below is dynamic instead of lexical on older versions.
+(defvar trusted-content)
+
(defmacro flycheck-buttercup-with-resource-buffer (resource-file &rest body)
"Create a temp buffer from a RESOURCE-FILE and execute BODY.
The absolute file name of RESOURCE-FILE is determined with
-`flycheck-buttercup-resource-filename'."
+`flycheck-buttercup-resource-filename'. The resource file is
+marked as trusted via `trusted-content', so that checkers gated
+on `trusted-content-p' (e.g. `emacs-lisp') remain enabled."
(declare (indent 1))
- `(flycheck-buttercup-with-file-buffer
- (flycheck-buttercup-resource-filename ,resource-file)
- ,@body))
+ `(let ((trusted-content :all))
+ (flycheck-buttercup-with-file-buffer
+ (flycheck-buttercup-resource-filename ,resource-file)
+ ,@body)))
;;; Syntax checking in tests
diff --git a/flycheck.el b/flycheck.el
index e82aa09191..7b2c55f45e 100644
--- a/flycheck.el
+++ b/flycheck.el
@@ -8726,6 +8726,20 @@ This variable has no effect, if
(member (file-name-nondirectory (buffer-file-name))
'("Cask" "Carton" ".dir-locals.el" ".dir-locals-2.el"))))))
+(defun flycheck--emacs-lisp-byte-compile-enabled-p ()
+ "Check whether to enable the Emacs Lisp byte compiler checker.
+
+On Emacs 30+, the checker is only enabled for trusted files, to
+mitigate CVE-2024-53920: byte-compilation involves macro expansion
+which can execute arbitrary code. Customize `trusted-content' to
+mark files or directories as trusted.
+
+Checkdoc doesn't expand macros, so `emacs-lisp-checkdoc' stays
+enabled for untrusted files, like in Emacs core."
+ (and (flycheck--emacs-lisp-enabled-p)
+ (or (not (fboundp 'trusted-content-p))
+ (trusted-content-p))))
+
(defun flycheck--emacs-lisp-checkdoc-enabled-p ()
"Check whether to enable Emacs Lisp Checkdoc in the current buffer."
(and (flycheck--emacs-lisp-enabled-p)
@@ -8735,6 +8749,11 @@ This variable has no effect, if
(flycheck-define-checker emacs-lisp
"An Emacs Lisp syntax checker using the Emacs Lisp Byte compiler.
+On Emacs 30+, this checker is only enabled for files the user has
+marked as trusted via the `trusted-content' variable, to mitigate
+CVE-2024-53920 (byte-compilation involves macro expansion which can
+execute arbitrary code).
+
See Info Node `(elisp)Byte Compilation'."
:command ("emacs" (eval flycheck-emacs-args)
(eval
@@ -8784,7 +8803,7 @@ See Info Node `(elisp)Byte Compilation'."
(flycheck-collapse-error-message-whitespace
(flycheck-sanitize-errors errors))))
:modes (emacs-lisp-mode lisp-interaction-mode)
- :enabled flycheck--emacs-lisp-enabled-p
+ :enabled flycheck--emacs-lisp-byte-compile-enabled-p
:predicate
(lambda ()
;; Do not check buffers that should not be byte-compiled. The checker
diff --git a/test/specs/languages/test-emacs-lisp.el
b/test/specs/languages/test-emacs-lisp.el
index c850891f18..04be162af3 100644
--- a/test/specs/languages/test-emacs-lisp.el
+++ b/test/specs/languages/test-emacs-lisp.el
@@ -57,6 +57,25 @@
:to-equal
(seq-sort #'string-lessp checkdoc-relevant-vars)))))
+ (describe "Trusted content (CVE-2024-53920)"
+
+ (it "disables byte compilation for untrusted files"
+ (assume (fboundp 'trusted-content-p) "Requires Emacs 30+")
+ (flycheck-buttercup-with-resource-buffer
"language/emacs-lisp/warnings.el"
+ (emacs-lisp-mode)
+ (let ((trusted-content nil))
+ (expect (flycheck-may-use-checker 'emacs-lisp)
+ :not :to-be-truthy)
+ ;; Checkdoc doesn't expand macros, so it stays enabled
+ (expect (flycheck-may-use-checker 'emacs-lisp-checkdoc)
+ :to-be-truthy))))
+
+ (it "enables byte compilation for trusted files"
+ (assume (fboundp 'trusted-content-p) "Requires Emacs 30+")
+ (flycheck-buttercup-with-resource-buffer
"language/emacs-lisp/warnings.el"
+ (emacs-lisp-mode)
+ (expect (flycheck-may-use-checker 'emacs-lisp) :to-be-truthy))))
+
(describe "Checker tests"
(flycheck-buttercup-def-checker-test (emacs-lisp emacs-lisp-checkdoc)
emacs-lisp nil
(flycheck-buttercup-should-syntax-check