The Emacs security settings that might silently compromise your system

Emacs ships with default settings intended for backward compatibility and convenience over strict security. The following settings enforce TLS certificate verification, reduce unintended ffap network lookups, restrict the evaluation of potentially unsafe local file, and directory variables, automated package review system, and protect authentication credentials stored by Emacs.

Network and communication security

By default, Emacs prompts the user interactively if a connection appears untrustworthy. You can additionally require certificate validation to fail at the TLS library level, causing invalid certificates to result in a connection error.

Requiring certificate validation at the TLS layer reduces the possibility of accidentally accepting an invalid certificate in response to an interactive warning.

Define these variables in your early-init.el to ensure the settings are established before startup code initiates network connections:

(setq gnutls-verify-error t)
(setq tls-checktrust t)
(setq gnutls-min-prime-bits 3072)
  • gnutls-verify-error: Controls GnuTLS certificate verification. Setting this to t makes any certificate validation failure fatal.
  • tls-checktrust: Controls external TLS binaries. Setting this to t ensures certificate validation is enforced if Emacs falls back to using external tools.
  • gnutls-min-prime-bits: Defines the minimum acceptable size for Diffie-Hellman key exchange primes. Setting this to 3072 rejects handshakes using primes smaller than 3072 bits.

The benefit of strictly enforcing connection security at the TLS layer is preventing the accidental acceptance of invalid certificates or weak cryptography.

Find file at point network requests

The ffap (Find File At Point) package scans text around point to identify file paths, URLs, and hostnames. This triggers when you invoke an ffap command, most commonly find-file-at-point, which replaces standard C-x C-f if you have (ffap-bindings) enabled, while your cursor is resting on or near a string of text that resembles a domain name.

Setting ffap-machine-p-known to 'reject prevents FFAP from probing hostnames with known domains:

(setq ffap-machine-p-known 'reject)

The tradeoff is that ffap will no longer automatically recognize hostnames as remote connection targets, meaning you must enter remote host paths explicitly.

Encrypting auth sources

Emacs' auth-source uses files such as ~/.authinfo and ~/.netrc to store authentication credentials that other Emacs packages can retrieve when connecting to remote services. For example:

  • Tramp: Passwords for remote server access.
  • Gnus and Message: Credentials for mail retrieval (IMAP, POP3) and transmission (SMTP).

An auth-source entry can contain information such as a hostname, username, password, port, or protocol. Because these files may contain sensitive credentials, storing them as plain text exposes them to any process or user that can read the file.

To enforce the exclusive use of an encrypted file and prevent accidental plain-text credential storage, redefine the authentication sources list:

(setq auth-sources '("~/.authinfo.gpg"))

Additional security configurations:

  • To encrypt the file using specific GPG public keys, define the recipients using auth-source-gpg-encrypt-to:
(setq auth-source-gpg-encrypt-to '("[email protected]"))
  • Emacs can cache passwords to minimize prompt interruptions. The cache expiration can be configured using auth-source-cache-expiry:
(setq auth-source-cache-expiry 3600)

Clear auth-source cache when the user is idle

The auth-source library uses password cache to store authentication data in memory. By default, auth-source-do-cache is enabled (t) and auth-source-cache-expiry is set to 7200 seconds (2 hours). You can restrict this credential exposure using idle timers, targeted cache clearing, or by disabling the cache entirely.

Use an idle timer to purge credentials after a period of inactivity instead of waiting for the absolute cache expiry limit:

(defun my-security-clear-caches ()
  "Clear all cached authentication data managed by auth-source."
  (when (fboundp 'auth-source-forget-all-cached)
    (auth-source-forget-all-cached)))

(run-with-idle-timer 900 t #'my-security-clear-caches)

The benefit is that it limits memory exposure to 15 minutes of idle time. The tradeoff is that background operations requiring authentication may fail or block while awaiting a passphrase when returning to the editor.

Symbol shorthand code execution

Emacs 28.1 added a feature called symbol shorthands (read-symbol-shorthands). A vulnerability exists in Emacs versions 28.1 through 31 pretest where this feature can be abused to trigger arbitrary code execution simply by opening a specially crafted file. The malicious execution occurs immediately, even before the file contents are displayed.

The exploit relies on Emacs evaluating symbol shorthands during unsafe intern calls in vc-find-backend-function and c-compose-keywords-list. Emacs 31.1 mitigates the vulnerability. Earlier versions, including affected Emacs 31 pretest versions, remain vulnerable unless the mitigation is applied manually.

For users on Emacs 31 pretest or older, you can implement a mitigation by defining an advice function that locally disables symbol shorthands and applying it around the vulnerable operations.

(defun my-suppress-shorthands (orig &rest args)
  "Call ORIG function with ARGS while binding `read-symbol-shorthands' to nil.
ORIG is the original function being advised.
ARGS is the list of arguments passed to the original function.
This acts as advice to prevent arbitrary code execution via symbol shorthands
during unsafe operations like interning symbols on file open."
  (let (read-symbol-shorthands)
    (apply orig args)))

;; A workaround patch (Commit 8466eb44) was applied to the emacs-31 release
;; branch on August 5, 2026. Early pretest versions of Emacs 31 do not
;; include this mitigation.
(when (< emacs-major-version 32)
  (advice-add 'vc-find-backend-function :around #'my-suppress-shorthands)

  (with-eval-after-load 'cc-fonts
    (advice-add 'c-compose-keywords-list :around #'my-suppress-shorthands)))

This protects the editor from silent code execution attacks embedded in untrusted source files without requiring an upgrade to an unreleased Emacs version. The tradeoff is that it modifies core function behavior via advice, though the impact on version control and C/C++ fontification performance is negligible.

Package Management

Emacs 31.1 added package-review-policy, an automated package review system, allowing inspection of upstream code changes before installation:

(setq package-review-policy t)

Setting package-review-policy to t causes Emacs to require a review of packages before installation or upgrade. The package is unpacked into a temporary review directory, where the source can be compared with the previous installation (diff), and reviewed. The package is installed only if the review succeeds.

The main downside is that updates can no longer run in the background. Having to review diffs by hand gets tedious when upgrading multiple packages at once.

Securing .dir-locals.el and local variables

Emacs automatically applies project-specific configurations through file-local and directory-local (.dir-locals.el) variables when opening a file or directory. While this feature ensures consistent settings across environments, it can cause security risks and persistent prompt fatigue when editing source code. Malicious .dir-locals.el files or file-local variables containing eval forms can execute arbitrary Lisp code if Emacs is configured to evaluate them, or if the user explicitly approves the relevant prompt. This article outlines configurations for securing file-local and .dir-locals.el variables:
Emacs .dir-locals.el and Local Variables - Securing and Reducing Prompts.

Leave a Reply

Your email address will not be published. Required fields are marked *