summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReepca Russelstein <reepca@russelstein.xyz>2025-07-24 17:35:37 -0500
committerLudovic Courtès <ludo@gnu.org>2025-09-01 16:13:11 +0200
commit2a333541e8f1907ae0bc80cf500a99567ca46d08 (patch)
tree57fd3e86b5a8b802b8a75baad5d98feaf4ecbb58
parent43bb79fc29e7f4f2ea06be138df195609b11ea97 (diff)
perform-download: Ensure reading never evaluates code.
Since this is used to implement the "download" and "git-download" builtins, which are run outside of any chroot, this is trusted code with respect to the user-supplied strings it reads. * guix/scripts/perform-download.scm (read/safe): new procedure. (perform-download, perform-git-download): use it. (guix-perform-download): explicitly set 'read-eval?' to #f and 'read-hash-procedures' to '(). #f is the default value of 'read-eval?' on startup, but set it anyway to be certain. Change-Id: I93cb8e32607a6f9a559a26c1cbd6b88212ead884 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
-rw-r--r--guix/scripts/perform-download.scm27
1 files changed, 19 insertions, 8 deletions
diff --git a/guix/scripts/perform-download.scm b/guix/scripts/perform-download.scm
index 5079d0ea71..64e4336c96 100644
--- a/guix/scripts/perform-download.scm
+++ b/guix/scripts/perform-download.scm
@@ -43,6 +43,11 @@
(let ((module (make-fresh-user-module)))
(module-use! module (resolve-interface '(guix base32)))
module))
+(define* (read/safe #:optional (port (current-input-port)))
+ (with-fluids ((read-eval? #f))
+ (parameterize ((read-hash-procedures '()))
+ (read port))))
+
(define* (perform-download drv output
#:key print-build-trace?)
@@ -60,7 +65,7 @@ Note: OUTPUT may differ from the 'out' value of DRV, notably for 'bmCheck' or
(unless url
(leave (G_ "~a: missing URL~%") (derivation-file-name drv)))
- (let* ((url (call-with-input-string url read))
+ (let* ((url (call-with-input-string url read/safe))
(drv-output (assoc-ref (derivation-outputs drv) "out"))
(algo (derivation-output-hash-algo drv-output))
(hash (derivation-output-hash drv-output)))
@@ -68,21 +73,21 @@ Note: OUTPUT may differ from the 'out' value of DRV, notably for 'bmCheck' or
(when (parameterize ((%download-methods
(and download-methods
(call-with-input-string download-methods
- read))))
+ read/safe))))
(url-fetch url output
#:print-build-trace? print-build-trace?
#:mirrors (if mirrors
- (call-with-input-file mirrors read)
+ (call-with-input-file mirrors read/safe)
'())
#:content-addressed-mirrors
(if content-addressed-mirrors
(call-with-input-file content-addressed-mirrors
(lambda (port)
- (eval (read port) %user-module)))
+ (eval (read/safe port) %user-module)))
'())
#:disarchive-mirrors
(if disarchive-mirrors
- (call-with-input-file disarchive-mirrors read)
+ (call-with-input-file disarchive-mirrors read/safe)
'())
#:hashes `((,algo . ,hash))
@@ -108,9 +113,9 @@ Note: OUTPUT may differ from the 'out' value of DRV, notably for 'bmCheck' or
(unless commit
(leave (G_ "~a: missing Git commit~%") (derivation-file-name drv)))
- (let* ((url (call-with-input-string url read))
+ (let* ((url (call-with-input-string url read/safe))
(recursive? (and recursive?
- (call-with-input-string recursive? read)))
+ (call-with-input-string recursive? read/safe)))
(drv-output (assoc-ref (derivation-outputs drv) "out"))
(algo (derivation-output-hash-algo drv-output))
(hash (derivation-output-hash drv-output)))
@@ -123,7 +128,7 @@ Note: OUTPUT may differ from the 'out' value of DRV, notably for 'bmCheck' or
(parameterize ((%download-methods
(and download-methods
(call-with-input-string download-methods
- read))))
+ read/safe))))
;; Note: When doing a '--check' build, DRV-OUTPUT and OUTPUT are
;; different, hence the #:item argument below.
(git-fetch-with-fallback url commit output
@@ -153,6 +158,12 @@ Note: OUTPUT may differ from the 'out' value of DRV, notably for 'bmCheck' or
(#f #f)
(str (string-contains str "print-extended-build-trace=1"))))
+ ;; We read untrusted input, best to be sure this is #f!
+ (fluid-set! read-eval? #f)
+ ;; ... and out of an abundance of caution, remove the ability to use '#.'
+ ;; constructs entirely
+ (read-hash-procedures '())
+
;; This program must be invoked by guix-daemon under an unprivileged UID to
;; prevent things downloading from 'file:///etc/shadow' or arbitrary code
;; execution via the content-addressed mirror procedures. (That means we