Line
Link Here
|
|
Do not set `trusted-content` in major modes |
|
Do not set `trusted-content` in major modes |
1 |
(elisp-flymake-byte-compile): Improve UX with `debug-on-error` |
1 |
(elisp-flymake-byte-compile): Improve UX with `debug-on-error` |
2 |
Document 'trusted-content |
2 |
Document 'trusted-content |
3 |
* lisp/files.el (trusted-content-p): Make `:all` work in non-file buffers |
3 |
* lisp/files.el (trusted-content-p): Make `:all` work in non-file buffers |
4 |
trusted-content: Adjust the last patch based on preliminary feedback |
4 |
trusted-content: Adjust the last patch based on preliminary feedback |
5 |
elisp-mode.el: Disable Flymake byte-compile backend in untrusted files |
5 |
elisp-mode.el: Disable Flymake byte-compile backend in untrusted files |
6 |
|
6 |
|
7 |
(elisp--local-variables): Fix recent regression |
7 |
(elisp--local-variables): Fix recent regression |
8 |
-- emacs-26.3/doc/emacs/misc.texi |
8 |
++ emacs-26.3/doc/emacs/misc.texi |
Lines 279-284
Link Here
|
279 |
you can set @code{enable-local-variables} to @code{:all}. @xref{Safe |
279 |
you can set @code{enable-local-variables} to @code{:all}. @xref{Safe |
280 |
File Variables}. |
280 |
File Variables}. |
281 |
|
281 |
|
|
|
282 |
@cindex trusted files and directories |
283 |
Loading a file of Emacs Lisp code with @code{load-file} or |
284 |
@code{load-library} (@pxref{Lisp Libraries}) can execute some of the |
285 |
Lisp code in the file being loaded, so you should only load Lisp files |
286 |
whose source you trust. However, some Emacs features can in certain |
287 |
situations execute Lisp code even without your explicit command or |
288 |
request. For example, Flymake, the on-the-fly syntax checker for Emacs |
289 |
(@pxref{Top,,, flymake, GNU Flymake}), if it is enabled, can |
290 |
automatically execute some of the code in a Lisp file you visit as part |
291 |
of its syntax-checking job. Similarly, some completion commands |
292 |
(@pxref{Completion}) in buffers visiting Lisp files sometimes need to |
293 |
expand Lisp macros for best results. In these cases, just visiting a |
294 |
Lisp file and performing some editing in it could trigger execution of |
295 |
Lisp code. If the visited file came from an untrusted source, it could |
296 |
include dangerous or even malicious code that Emacs would execute in |
297 |
those situations. |
298 |
|
299 |
To protect against this, Emacs disables execution of Lisp code by |
300 |
Flymake, completion, and some other features, unless the visited file is |
301 |
@dfn{trusted}. It is up to you to specify which files on your system |
302 |
should be trusted, by customizing the user option |
303 |
@code{trusted-content}. |
304 |
|
305 |
@defopt trusted-content |
306 |
The value of this option is @code{nil} by default, which means no file |
307 |
is trusted. You can customize the variable to be a list of one or more |
308 |
names of trusted files and directories. A file name that ends in a |
309 |
slash @file{/} is interpreted as a directory, which means all its files |
310 |
and subdirectories are also trusted. A special value @code{:all} means |
311 |
@emph{all} the files and directories on your system should be trusted; |
312 |
@strong{this is not recommended}, as it opens a gaping security hole. |
313 |
@end defopt |
314 |
|
282 |
@xref{Security Considerations,,, elisp, The Emacs Lisp Reference |
315 |
@xref{Security Considerations,,, elisp, The Emacs Lisp Reference |
283 |
Manual}, for more information about security considerations when using |
316 |
Manual}, for more information about security considerations when using |
284 |
Emacs as part of a larger application. |
317 |
Emacs as part of a larger application. |
285 |
-- emacs-26.3/lisp/files.el |
318 |
++ emacs-26.3/lisp/files.el |
Lines 584-589
Link Here
|
584 |
Some modes may wish to set this to nil to prevent directory-local |
584 |
Some modes may wish to set this to nil to prevent directory-local |
585 |
settings being applied, but still respect file-local ones.") |
585 |
settings being applied, but still respect file-local ones.") |
586 |
|
586 |
|
|
|
587 |
(defcustom trusted-content nil |
588 |
"List of files and directories whose content we trust. |
589 |
Be extra careful here since trusting means that Emacs might execute the |
590 |
code contained within those files and directories without an explicit |
591 |
request by the user. |
592 |
One important case when this might happen is when `flymake-mode' is |
593 |
enabled (for example, when it is added to a mode hook). |
594 |
Each element of the list should be a string: |
595 |
- If it ends in \"/\", it is considered as a directory name and means that |
596 |
Emacs should trust all the files whose name has this directory as a prefix. |
597 |
- Otherwise, it is considered a file name. |
598 |
Use abbreviated file names. For example, an entry \"~/mycode/\" means |
599 |
that Emacs will trust all the files in your directory \"mycode\". |
600 |
This variable can also be set to `:all', in which case Emacs will trust |
601 |
all files, which opens a gaping security hole. Emacs Lisp authors |
602 |
should note that this value must never be set by a major or minor mode." |
603 |
:type '(choice (repeat :tag "List" file) |
604 |
(const :tag "Trust everything (DANGEROUS!)" :all)) |
605 |
:version "30.1") |
606 |
(put 'trusted-content 'risky-local-variable t) |
607 |
|
608 |
(defun trusted-content-p () |
609 |
"Return non-nil if we trust the contents of the current buffer. |
610 |
Here, \"trust\" means that we are willing to run code found inside of it. |
611 |
See also `trusted-content'." |
612 |
;; We compare with `buffer-file-truename' i.s.o `buffer-file-name' |
613 |
;; to try and avoid marking as trusted a file that's merely accessed |
614 |
;; via a symlink that happens to be inside a trusted dir. |
615 |
(and (not untrusted-content) |
616 |
(or |
617 |
(eq trusted-content :all) |
618 |
(and |
619 |
buffer-file-truename |
620 |
(with-demoted-errors "trusted-content-p: %S" |
621 |
(let ((exists (file-exists-p buffer-file-truename))) |
622 |
(or |
623 |
;; We can't avoid trusting the user's init file. |
624 |
(if (and exists user-init-file) |
625 |
(file-equal-p buffer-file-truename user-init-file) |
626 |
(equal buffer-file-truename user-init-file)) |
627 |
(let ((file (abbreviate-file-name buffer-file-truename)) |
628 |
(trusted nil)) |
629 |
(dolist (tf trusted-content) |
630 |
(when (or (if exists (file-equal-p tf file) (equal tf file)) |
631 |
;; We don't use `file-in-directory-p' here, because |
632 |
;; we want to err on the conservative side: "guilty |
633 |
;; until proven innocent". |
634 |
(and (string-suffix-p "/" tf) |
635 |
(string-prefix-p tf file))) |
636 |
(setq trusted t))) |
637 |
trusted)))))))) |
638 |
|
587 |
;; This is an odd variable IMO. |
639 |
;; This is an odd variable IMO. |
588 |
;; You might wonder why it is needed, when we could just do: |
640 |
;; You might wonder why it is needed, when we could just do: |
589 |
;; (set (make-local-variable 'enable-local-variables) nil) |
641 |
;; (set (make-local-variable 'enable-local-variables) nil) |
590 |
-- emacs-26.3/lisp/ielm.el |
642 |
++ emacs-26.3/lisp/ielm.el |
Lines 613-619
Link Here
|
613 |
(unless (comint-check-proc "*ielm*") |
613 |
(unless (comint-check-proc "*ielm*") |
614 |
(with-current-buffer (get-buffer-create "*ielm*") |
614 |
(with-current-buffer (get-buffer-create "*ielm*") |
615 |
(unless (zerop (buffer-size)) (setq old-point (point))) |
615 |
(unless (zerop (buffer-size)) (setq old-point (point))) |
616 |
(inferior-emacs-lisp-mode))) |
616 |
(inferior-emacs-lisp-mode) |
|
|
617 |
(setq-local trusted-content :all))) |
617 |
(pop-to-buffer-same-window "*ielm*") |
618 |
(pop-to-buffer-same-window "*ielm*") |
618 |
(when old-point (push-mark old-point)))) |
619 |
(when old-point (push-mark old-point)))) |
619 |
|
620 |
|
620 |
-- emacs-26.3/lisp/progmodes/elisp-mode.el |
621 |
++ emacs-26.3/lisp/progmodes/elisp-mode.el |
Lines 309-314
Link Here
|
309 |
|
309 |
|
310 |
(defvar warning-minimum-log-level) |
310 |
(defvar warning-minimum-log-level) |
311 |
|
311 |
|
|
|
312 |
(defvar elisp--local-macroenv |
313 |
`((cl-eval-when . ,(lambda (&rest args) `(progn . ,(cdr args)))) |
314 |
(eval-when-compile . ,(lambda (&rest args) `(progn . ,args))) |
315 |
(eval-and-compile . ,(lambda (&rest args) `(progn . ,args)))) |
316 |
"Environment to use while tentatively expanding macros. |
317 |
This is used to try and avoid the most egregious problems linked to the |
318 |
use of `macroexpand-all' as a way to find the \"underlying raw code\".") |
319 |
|
320 |
(defvar elisp--macroexpand-untrusted-warning t) |
321 |
|
322 |
(defun elisp--safe-macroexpand-all (sexp) |
323 |
(if (not (trusted-content-p)) |
324 |
;; FIXME: We should try and do better here, either using a notion |
325 |
;; of "safe" macros, or with `bwrap', or ... |
326 |
(progn |
327 |
(when elisp--macroexpand-untrusted-warning |
328 |
(setq-local elisp--macroexpand-untrusted-warning nil) ;Don't spam! |
329 |
(let ((inhibit-message t)) ;Only log. |
330 |
(message "Completion of local vars is disabled in %s (untrusted content)" |
331 |
(buffer-name)))) |
332 |
sexp) |
333 |
(let ((macroexpand-advice |
334 |
(lambda (expander form &rest args) |
335 |
(condition-case err |
336 |
(apply expander form args) |
337 |
(error |
338 |
(message "Ignoring macroexpansion error: %S" err) form))))) |
339 |
(unwind-protect |
340 |
;; Silence any macro expansion errors when |
341 |
;; attempting completion at point (bug#58148). |
342 |
(let ((inhibit-message t) |
343 |
(macroexp-inhibit-compiler-macros t) |
344 |
(warning-minimum-log-level :emergency)) |
345 |
(advice-add 'macroexpand-1 :around macroexpand-advice) |
346 |
(macroexpand-all sexp elisp--local-macroenv)) |
347 |
(advice-remove 'macroexpand-1 macroexpand-advice))))) |
348 |
|
312 |
(defun elisp--local-variables () |
349 |
(defun elisp--local-variables () |
313 |
"Return a list of locally let-bound variables at point." |
350 |
"Return a list of locally let-bound variables at point." |
314 |
(save-excursion |
351 |
(save-excursion |
Lines 324-340
Link Here
|
324 |
(car (read-from-string |
361 |
(car (read-from-string |
325 |
(concat txt "elisp--witness--lisp" closer))) |
362 |
(concat txt "elisp--witness--lisp" closer))) |
326 |
((invalid-read-syntax end-of-file) nil))) |
363 |
((invalid-read-syntax end-of-file) nil))) |
327 |
(macroexpand-advice (lambda (expander form &rest args) |
364 |
(vars (elisp--local-variables-1 |
328 |
(condition-case nil |
365 |
nil (elisp--safe-macroexpand-all sexp)))) |
329 |
(apply expander form args) |
|
|
330 |
(error form)))) |
331 |
(sexp |
332 |
(unwind-protect |
333 |
(let ((warning-minimum-log-level :emergency)) |
334 |
(advice-add 'macroexpand :around macroexpand-advice) |
335 |
(macroexpand-all sexp)) |
336 |
(advice-remove 'macroexpand macroexpand-advice))) |
337 |
(vars (elisp--local-variables-1 nil sexp))) |
338 |
(delq nil |
366 |
(delq nil |
339 |
(mapcar (lambda (var) |
367 |
(mapcar (lambda (var) |
340 |
(and (symbolp var) |
368 |
(and (symbolp var) |
Lines 1672-1677
Link Here
|
1672 |
"A Flymake backend for elisp byte compilation. |
1700 |
"A Flymake backend for elisp byte compilation. |
1673 |
Spawn an Emacs process that byte-compiles a file representing the |
1701 |
Spawn an Emacs process that byte-compiles a file representing the |
1674 |
current buffer state and calls REPORT-FN when done." |
1702 |
current buffer state and calls REPORT-FN when done." |
|
|
1703 |
(unless (trusted-content-p) |
1704 |
;; FIXME: Use `bwrap' and friends to compile untrusted content. |
1705 |
;; FIXME: We emit a message *and* signal an error, because by default |
1706 |
;; Flymake doesn't display the warning it puts into "*flmake log*". |
1707 |
(message "Disabling elisp-flymake-byte-compile in %s (untrusted content)" |
1708 |
(buffer-name)) |
1709 |
(user-error "Disabling elisp-flymake-byte-compile in %s (untrusted content)" |
1710 |
(buffer-name))) |
1675 |
(when elisp-flymake--byte-compile-process |
1711 |
(when elisp-flymake--byte-compile-process |
1676 |
(when (process-live-p elisp-flymake--byte-compile-process) |
1712 |
(when (process-live-p elisp-flymake--byte-compile-process) |
1677 |
(kill-process elisp-flymake--byte-compile-process))) |
1713 |
(kill-process elisp-flymake--byte-compile-process))) |
1678 |
-- emacs-26.3/lisp/simple.el |
1714 |
++ emacs-26.3/lisp/simple.el |
Lines 1502-1507
Link Here
|
1502 |
(eldoc-mode 1) |
1502 |
(eldoc-mode 1) |
1503 |
(add-hook 'completion-at-point-functions |
1503 |
(add-hook 'completion-at-point-functions |
1504 |
#'elisp-completion-at-point nil t) |
1504 |
#'elisp-completion-at-point nil t) |
|
|
1505 |
(setq-local trusted-content :all) |
1505 |
(run-hooks 'eval-expression-minibuffer-setup-hook)) |
1506 |
(run-hooks 'eval-expression-minibuffer-setup-hook)) |
1506 |
(read-from-minibuffer prompt initial-contents |
1507 |
(read-from-minibuffer prompt initial-contents |
1507 |
read-expression-map t |
1508 |
read-expression-map t |
1508 |
-- emacs-26.3/lisp/startup.el |
1509 |
++ emacs-26.3/lisp/startup.el |
Lines 1357-1364
Link Here
|
1357 |
;; If *scratch* exists and init file didn't change its mode, initialize it. |
1357 |
;; If *scratch* exists and init file didn't change its mode, initialize it. |
1358 |
(if (get-buffer "*scratch*") |
1358 |
(if (get-buffer "*scratch*") |
1359 |
(with-current-buffer "*scratch*" |
1359 |
(with-current-buffer "*scratch*" |
1360 |
(if (eq major-mode 'fundamental-mode) |
1360 |
(when (eq major-mode 'fundamental-mode) |
1361 |
(funcall initial-major-mode)))) |
1361 |
(funcall initial-major-mode) |
|
|
1362 |
(when (eq initial-major-mode 'lisp-interaction-mode) |
1363 |
(setq-local trusted-content :all))))) |
1362 |
|
1364 |
|
1363 |
;; Load library for our terminal type. |
1365 |
;; Load library for our terminal type. |
1364 |
;; User init file can set term-file-prefix to nil to prevent this. |
1366 |
;; User init file can set term-file-prefix to nil to prevent this. |