This is a minimal recipe to reproduce the problem:

    $ mmdebstrap bookworm /dev/null --include=emacs-nox,ca-certificates,gnupg 
--customize-hook='chroot $1 emacs -Q -f package-list-packages'

Inside the emacs that starts, you'll see (after a couple of seconds):

    Failed to verify signature archive-contents.sig:
    No public key for 645357D2883A0966 created at 2024-06-10T21:10:04+0000 
using EDDSA
    Command output:
    gpg: Signature made Mon Jun 10 21:10:04 2024 UTC
    gpg:                using EDDSA key 0327BE68D64D9A1A66859F15645357D2883A0966
    gpg: Can't check signature: No public key

You will need a controlling terminal better than TERM=dumb.
If you don't have a terminal (e.g. you're a CI/CD script), this variant hook 
works:

    bash5$ D12_shell --quiet --include=emacs-nox,ca-certificates,gnupg 
--customize-hook='chroot $1 emacs --batch -Q -f package-list-packages -f 
package--download-and-read-archives'
    Contacting host: elpa.gnu.org:443
    Contacting host: elpa.gnu.org:443
    Failed to download ‘gnu’ archive.
    Debugger entered--Lisp error: (bad-signature "archive-contents.sig")
      signal(bad-signature ("archive-contents.sig"))
      
package--check-signature-content("\210u\4\0\26\10\0\35\26!\4\3'\276h\326M\232\32f\205\237\25dSW\322\210:\11f\5\2fgk\254\0\n\11\20dSW\322\210:\11f\346..."
 "(1\n (adoc-mode .\n\11    [(0 7 0)\n\11     ((emacs\n\11    ..." 
"archive-contents.sig")
      #f(compiled-function () #<bytecode -0xe41cb77d185892b>)()
      #f(compiled-function (status) #<bytecode 0xf5987e8eb8f468e>)((:peer 
(:certificates ((:version 3 :serial-number 
"04:dd:78:56:c7:1c:b9:a5:4d:6b:b6:ee:e1:5b:8f:6a:4b..." :issuer "C=US,O=Let's 
Encrypt,CN=R3" :valid-from "2024-06-03" :valid-to "2024-09-01" :subject 
"CN=elpa.nongnu.org" :public-key-algorithm "RSA" :certificate-security-level 
"Medium" :signature-algorithm "RSA-SHA256" :public-key-id 
"sha1:8b:16:cb:f9:32:f1:7d:1f:ec:8a:14:d2:91:ff:3f:..." :certificate-id 
"sha1:0c:09:41:11:91:e6:fd:59:a3:26:24:60:90:e4:bd:..." :pem "-----BEGIN 
CERTIFICATE-----\nMIIE6zCCA9OgAwIBAgISBN...") (:version 3 :serial-number 
"00:91:2b:08:4a:cf:0c:18:a7:53:f6:d6:2e:25:a7:5f:5a" :issuer "C=US,O=Internet 
Security Research Group,CN=ISRG Ro..." :valid-from "2020-09-04" :valid-to 
"2025-09-15" :subject "C=US,O=Let's Encrypt,CN=R3" :public-key-algorithm "RSA" 
:certificate-security-level "Medium" :signature-algorithm "RSA-SHA256" 
:public-key-id "sha1:8a:93:82:f4:c8:04:08:34:5e:5b:c2:f8:d7:55:d3:..." 
:certificate-id "sha1:a0:53:37:5b:fe:84:e8:b7:48:78:2c:7c:ee:15:82:..." :pem 
"-----BEGIN CERTIFICATE-----\nMIIFFjCCAv6gAwIBAgIRAJ...")) :certificate 
(:version 3 :serial-number 
"04:dd:78:56:c7:1c:b9:a5:4d:6b:b6:ee:e1:5b:8f:6a:4b..." :issuer "C=US,O=Let's 
Encrypt,CN=R3" :valid-from "2024-06-03" :valid-to "2024-09-01" :subject 
"CN=elpa.nongnu.org" :public-key-algorithm "RSA" :certificate-security-level 
"Medium" :signature-algorithm "RSA-SHA256" :public-key-id 
"sha1:8b:16:cb:f9:32:f1:7d:1f:ec:8a:14:d2:91:ff:3f:..." :certificate-id 
"sha1:0c:09:41:11:91:e6:fd:59:a3:26:24:60:90:e4:bd:..." :pem "-----BEGIN 
CERTIFICATE-----\nMIIE6zCCA9OgAwIBAgISBN...") :key-exchange "ECDHE-RSA" 
:protocol "TLS1.3" :cipher "AES-256-GCM" :mac "AEAD" :encrypt-then-mac nil)))
      apply(#f(compiled-function (status) #<bytecode 0xf5987e8eb8f468e>) (:peer 
(:certificates ((:version 3 :serial-number 
"04:dd:78:56:c7:1c:b9:a5:4d:6b:b6:ee:e1:5b:8f:6a:4b..." :issuer "C=US,O=Let's 
Encrypt,CN=R3" :valid-from "2024-06-03" :valid-to "2024-09-01" :subject 
"CN=elpa.nongnu.org" :public-key-algorithm "RSA" :certificate-security-level 
"Medium" :signature-algorithm "RSA-SHA256" :public-key-id 
"sha1:8b:16:cb:f9:32:f1:7d:1f:ec:8a:14:d2:91:ff:3f:..." :certificate-id 
"sha1:0c:09:41:11:91:e6:fd:59:a3:26:24:60:90:e4:bd:..." :pem "-----BEGIN 
CERTIFICATE-----\nMIIE6zCCA9OgAwIBAgISBN...") (:version 3 :serial-number 
"00:91:2b:08:4a:cf:0c:18:a7:53:f6:d6:2e:25:a7:5f:5a" :issuer "C=US,O=Internet 
Security Research Group,CN=ISRG Ro..." :valid-from "2020-09-04" :valid-to 
"2025-09-15" :subject "C=US,O=Let's Encrypt,CN=R3" :public-key-algorithm "RSA" 
:certificate-security-level "Medium" :signature-algorithm "RSA-SHA256" 
:public-key-id "sha1:8a:93:82:f4:c8:04:08:34:5e:5b:c2:f8:d7:55:d3:..." 
:certificate-id "sha1:a0:53:37:5b:fe:84:e8:b7:48:78:2c:7c:ee:15:82:..." :pem 
"-----BEGIN CERTIFICATE-----\nMIIFFjCCAv6gAwIBAgIRAJ...")) :certificate 
(:version 3 :serial-number 
"04:dd:78:56:c7:1c:b9:a5:4d:6b:b6:ee:e1:5b:8f:6a:4b..." :issuer "C=US,O=Let's 
Encrypt,CN=R3" :valid-from "2024-06-03" :valid-to "2024-09-01" :subject 
"CN=elpa.nongnu.org" :public-key-algorithm "RSA" :certificate-security-level 
"Medium" :signature-algorithm "RSA-SHA256" :public-key-id 
"sha1:8b:16:cb:f9:32:f1:7d:1f:ec:8a:14:d2:91:ff:3f:..." :certificate-id 
"sha1:0c:09:41:11:91:e6:fd:59:a3:26:24:60:90:e4:bd:..." :pem "-----BEGIN 
CERTIFICATE-----\nMIIE6zCCA9OgAwIBAgISBN...") :key-exchange "ECDHE-RSA" 
:protocol "TLS1.3" :cipher "AES-256-GCM" :mac "AEAD" :encrypt-then-mac nil)))
      url-http-activate-callback()
      url-http-content-length-after-change-function(288 408 120)
      url-http-wait-for-headers-change-function(1 419 418)
      url-http-generic-filter(#<process elpa.nongnu.org> "HTTP/1.1 200 
OK\15\nDate: Tue, 11 Jun 2024 00:51:19 G...")
      accept-process-output(nil 0.05)
      
url-retrieve-synchronously("https://elpa.nongnu.org/nongnu/archive-contents";)
      package--with-response-buffer-1("https://elpa.nongnu.org/nongnu/"; 
#f(compiled-function () #<bytecode 0x45308209f3a0e3a>) :file "archive-contents" 
:async nil :error-function #f(compiled-function () #<bytecode 
-0xb2279de53cccd7d>) :noerror nil)
      package--download-one-archive(("nongnu" . 
"https://elpa.nongnu.org/nongnu/";) "archive-contents" nil)
      package--download-and-read-archives()
      command-line-1(("-f" "package-list-packages" "-f" 
"package--download-and-read-archives"))
      command-line()
      normal-top-level()

    umount: /tmp/mmdebstrap.3ylx2Gj6Gt/dev/null: target is busy.
    W: umount ./dev/null failed: 8192
    W: cannot unlink ./dev/null: Device or resource busy
    E: setup failed: E: command failed: chroot $1 emacs --batch -Q -f 
package-list-packages -f package--download-and-read-archives
    I: main() received signal PIPE: waiting for setup...
    I: removing tempdir /tmp/mmdebstrap.3ylx2Gj6Gt...
    E: mmdebstrap failed to run

This issue is not reproducible on Debian 13 (testing / trixie):

    bash5$ D13_shell --quiet --include=emacs-nox,ca-certificates,gnupg 
--customize-hook='chroot $1 emacs --batch -Q -f package-list-packages -f 
package--download-and-read-archives'
    Contacting host: elpa.gnu.org:443
    Contacting host: elpa.gnu.org:443
    Package refresh done
    Package refresh done
    Contacting host: elpa.nongnu.org:443
    Package refresh done
    I: running --customize-hook in shell: sh -c 'env -i TERM=screen 
PATH=/bin:/sbin chroot $1 bash; false' exec /tmp/mmdebstrap.IGMUZRQL75

This issue is not reproducible on Debian 12 with backported emacs:

    bash5$ mmdebstrap bookworm /dev/null --quiet 
--include=emacs-nox,ca-certificates,gnupg --customize-hook='chroot $1 emacs 
--batch -Q -f package-list-packages -f package--download-and-read-archives' 
--essential-hook='(echo Package: src:emacs; echo Pin: release 
a=stable-backports; echo Pin-Priority: 500) >>"$1/etc/apt/preferences.d/fuck"' 
'deb https://deb.debian.org/debian-security bookworm-security main' 'deb 
http://deb.debian.org/debian bookworm main' 'deb http://deb.debian.org/debian 
bookworm-updates main' 'deb http://deb.debian.org/debian 
bookworm-proposed-updates main' 'deb http://deb.debian.org/debian 
bookworm-backports main'
    Contacting host: elpa.gnu.org:443
    Contacting host: elpa.gnu.org:443
    Contacting host: elpa.nongnu.org:443
    Package refresh done
    Package refresh done
    umount: /tmp/mmdebstrap.LxIijFjees/dev/null: target is busy.

Note that if GPG isn't installed, package.el silently ignores the problem and 
allows MITM attacks:

    bash5$ D12_shell --quiet --include=emacs-nox,ca-certificates 
--customize-hook='chroot $1 emacs --batch -Q -f package-list-packages -f 
package--download-and-read-archives'
    Contacting host: elpa.gnu.org:443
    Contacting host: elpa.nongnu.org:443
    Package refresh done
    Package refresh done
    Package refresh done
    I: running --customize-hook in shell: sh -c 'env -i TERM=screen 
PATH=/bin:/sbin chroot $1 bash; false' exec /tmp/mmdebstrap.TOmuTk5OVd

Note that by default package.el ALSO allows MITM attacks simply by
having the attacker supply a downgraded repo, without signatures:

    (defcustom package-check-signature 'allow-unsigned ⋯) ; should be t!

Attachment: signature.asc
Description: PGP signature

Reply via email to