1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
From 60a3670af35e45d6c7b62872b300d914eba05478 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott@canonical.com>
Date: Mon, 30 Jun 2025 15:23:50 +0100
Subject: [PATCH 1/2] [lxd-import] lxd/daemon: Validate browser fetch metadata
if supplied to reject non-same-origin requests
Imported from stable-5.0 (Apache 2.0 licensed)
Signed-off-by: Thomas Parrott <thomas.parrott@canonical.com>
(cherry picked from commit 35ac3922d60763c24b1474459c4401f7c8ed619b)
(cherry picked from commit 569b7d472b4fc1622579e0aed32dd445ba6f53d0)
---
cmd/incusd/daemon.go | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/cmd/incusd/daemon.go b/cmd/incusd/daemon.go
index 29eb2155dcc..b310c67be1f 100644
--- a/cmd/incusd/daemon.go
+++ b/cmd/incusd/daemon.go
@@ -766,6 +766,12 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) {
return response.Forbidden(errors.New("You must be authenticated"))
}
+ // Protect against CSRF when using UI with browser that supports Fetch metadata.
+ // Deny Sec-Fetch-Site when set to cross-origin or same-site.
+ if slices.Contains([]string{"cross-site", "same-site"}, r.Header.Get("Sec-Fetch-Site")) {
+ return response.ErrorResponse(http.StatusForbidden, "Forbidden Sec-Fetch-Site header value")
+ }
+
// Call the access handler if there is one.
if action.AccessHandler != nil {
resp := action.AccessHandler(d, r)
From 033789e9f1f108e03313f375c39e349c2b300c44 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott@canonical.com>
Date: Mon, 30 Jun 2025 16:11:58 +0100
Subject: [PATCH 2/2] [lxd-import] test/suites/serverconfig: Check fetch
metadata header is validated
Imported from stable-5.0 (Apache 2.0 licensed)
Signed-off-by: Thomas Parrott <thomas.parrott@canonical.com>
(cherry picked from commit ab548b1cadd14c0699721fa8c0ef3f66916915e8)
(cherry picked from commit 7adcc8e8ed354e60663113c99e18a60d5fe58b81)
---
test/suites/serverconfig.sh | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/suites/serverconfig.sh b/test/suites/serverconfig.sh
index bef4aa3e654..074ffc96b86 100644
--- a/test/suites/serverconfig.sh
+++ b/test/suites/serverconfig.sh
@@ -15,6 +15,11 @@ test_server_config_access() {
# test authentication type
curl --unix-socket "$INCUS_DIR/unix.socket" "incus/1.0" | jq .metadata.auth_methods | grep tls
+
+ # test fetch metadata validation.
+ [ "$(curl --silent --unix-socket "$INCUS_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: same-origin' "incus/1.0")" = "200" ]
+ [ "$(curl --silent --unix-socket "$INCUS_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: cross-site' "incus/1.0")" = "403" ]
+ [ "$(curl --silent --unix-socket "$INCUS_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: same-site' "incus/1.0")" = "403" ]
}
test_server_config_storage() {
|