diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2026-06-24 11:34:05 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2026-07-02 19:42:48 +0200 |
| commit | 2ef8ed9f0df53bddf14bdecc2ea48c2d233213cc (patch) | |
| tree | 6f09ca584a6ddaf7928ab0d5ca5403fd9499f14d /tests/substitute.scm | |
| parent | 48cdb840ac38f32493e76e2c81570a1dd3c50f1f (diff) | |
substitutes: Ignore narinfos that don’t match the request [security fix].
Previously, by serving a valid, signed, and authorized narinfo that does not
match what the client asked for, an attacker could cause users to get the
wrong substitute.
* guix/substitutes.scm (fetch-narinfos)[handle-narinfo-response]: Check
whether the result of ‘read-narinfo’ matches ‘request’ and ignore it if it
doesn’t.
[do-fetch]: Likewise with ‘narinfo-from-file’.
* tests/substitute.scm ("query narinfo that returns different store path")
("substitute, narinfo does not match requested store item"): New tests.
Reported-by: Reepca Russelstein <reepca@russelstein.xyz>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Merges: #9665
Diffstat (limited to 'tests/substitute.scm')
| -rw-r--r-- | tests/substitute.scm | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/tests/substitute.scm b/tests/substitute.scm index 8f32bfa7281..b749561347a 100644 --- a/tests/substitute.scm +++ b/tests/substitute.scm | |||
| @@ -357,6 +357,29 @@ Deriver: foo.drv") | |||
| 357 | (lambda () | 357 | (lambda () |
| 358 | (guix-substitute "--query"))))))))) | 358 | (guix-substitute "--query"))))))))) |
| 359 | 359 | ||
| 360 | (test-equal "query narinfo that returns different store path" | ||
| 361 | ;; The narinfo is valid and authorized but its 'StorePath' field points to a | ||
| 362 | ;; different store item. | ||
| 363 | "" | ||
| 364 | |||
| 365 | (let ((prefix (string-append "StorePath: " (%store-prefix) | ||
| 366 | "/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-BAR | ||
| 367 | NarHash: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | ||
| 368 | References: bar baz\n"))) | ||
| 369 | (with-narinfo (string-append prefix | ||
| 370 | "Signature: " (signature-field prefix) " | ||
| 371 | URL: example.nar | ||
| 372 | Compression: none | ||
| 373 | NarSize: 42 | ||
| 374 | Deriver: foo.drv") | ||
| 375 | (string-trim-both | ||
| 376 | (with-output-to-string | ||
| 377 | (lambda () | ||
| 378 | (with-input-from-string (string-append "have " (%store-prefix) | ||
| 379 | "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo") | ||
| 380 | (lambda () | ||
| 381 | (guix-substitute "--query"))))))))) | ||
| 382 | |||
| 360 | (test-equal "query narinfo signed with authorized key" | 383 | (test-equal "query narinfo signed with authorized key" |
| 361 | (string-append (%store-prefix) "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo") | 384 | (string-append (%store-prefix) "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo") |
| 362 | 385 | ||
| @@ -893,6 +916,18 @@ System: mips64el-linux\n"))) | |||
| 893 | (lambda () | 916 | (lambda () |
| 894 | (false-if-exception (delete-file "substitute-retrieved"))))))) | 917 | (false-if-exception (delete-file "substitute-retrieved"))))))) |
| 895 | 918 | ||
| 919 | (test-quit "substitute, narinfo does not match requested store item" | ||
| 920 | "no valid substitute" | ||
| 921 | (with-http-server `((200 ,(string-append %narinfo "Signature: " | ||
| 922 | (signature-field %narinfo)))) | ||
| 923 | (parameterize ((substitute-urls (list (%local-url)))) | ||
| 924 | ;; Narinfo is valid, signed, and authorized but requested item is | ||
| 925 | ;; /bbb…-bar and narinfo is for /aaa…-foo. | ||
| 926 | (request-substitution (string-append (%store-prefix) | ||
| 927 | "/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-bar") | ||
| 928 | "substitute-retrieved") | ||
| 929 | #f))) | ||
| 930 | |||
| 896 | (test-end "substitute") | 931 | (test-end "substitute") |
| 897 | 932 | ||
| 898 | ;;; Local Variables: | 933 | ;;; Local Variables: |
