Version in base suite: 5.0.2+git20231211.1364ae4-9 Base version: lxd_5.0.2+git20231211.1364ae4-9 Target version: lxd_5.0.2+git20231211.1364ae4-9+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/l/lxd/lxd_5.0.2+git20231211.1364ae4-9.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/l/lxd/lxd_5.0.2+git20231211.1364ae4-9+deb13u1.dsc changelog | 12 +++++ gbp.conf | 2 patches/100-CVE-2025-54293.patch | 34 +++++++++++++++ patches/101-CVE-2025-54287.patch | 36 ++++++++++++++++ patches/102-CVE-2025-54288.patch | 35 +++++++++++++++ patches/103a-CVE-2025-54286.patch | 60 +++++++++++++++++++++++++++ patches/103b-CVE-2025-54286.patch | 84 ++++++++++++++++++++++++++++++++++++++ patches/series | 5 ++ 8 files changed, 267 insertions(+), 1 deletion(-) diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/changelog lxd-5.0.2+git20231211.1364ae4/debian/changelog --- lxd-5.0.2+git20231211.1364ae4/debian/changelog 2025-04-27 14:31:35.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/changelog 2025-10-02 16:23:38.000000000 +0000 @@ -1,3 +1,15 @@ +lxd (5.0.2+git20231211.1364ae4-9+deb13u1) trixie-security; urgency=high + + * Backport fixes for the following security issues that are unfixed by + Canonical in the stable-5.0 branch: + - CVE-2025-54293 / GHSA-472f-vmf2-pr3h + - CVE-2025-54287 / GHSA-w2hg-2v4p-vmh6 + - CVE-2025-54288 / GHSA-7232-97c6-j525 + * Backport fixes for the following security issues fixed by Canonical: + - CVE-2025-54286 / GHSA-p8hw-rfjg-689h + + -- Mathias Gibbens Thu, 02 Oct 2025 16:23:38 +0000 + lxd (5.0.2+git20231211.1364ae4-9) unstable; urgency=medium * d/control: diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/gbp.conf lxd-5.0.2+git20231211.1364ae4/debian/gbp.conf --- lxd-5.0.2+git20231211.1364ae4/debian/gbp.conf 2024-10-01 00:45:29.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/gbp.conf 2025-10-02 16:23:38.000000000 +0000 @@ -1,3 +1,3 @@ [DEFAULT] -debian-branch = debian/sid +debian-branch = debian/trixie dist = DEP14 diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/patches/100-CVE-2025-54293.patch lxd-5.0.2+git20231211.1364ae4/debian/patches/100-CVE-2025-54293.patch --- lxd-5.0.2+git20231211.1364ae4/debian/patches/100-CVE-2025-54293.patch 1970-01-01 00:00:00.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/patches/100-CVE-2025-54293.patch 2025-10-02 16:21:35.000000000 +0000 @@ -0,0 +1,34 @@ +From: Mathias Gibbens +Description: Backport fix for CVE-2025-54293. Note that the function validExecOutputFileName doesn't appear to exist in the 5.0-stable branch. +Origin: https://github.com/canonical/lxd/security/advisories/GHSA-472f-vmf2-pr3h +diff --git a/lxd/instance_logs.go b/lxd/instance_logs.go +index 4c45416ff..c6b5039d8 100644 +--- a/lxd/instance_logs.go ++++ b/lxd/instance_logs.go +@@ -150,6 +150,10 @@ func instanceLogsGet(d *Daemon, r *http.Request) response.Response { + } + + func validLogFileName(fname string) bool { ++ if !shared.IsFileName(fname) { ++ return false ++ } ++ + /* Let's just require that the paths be relative, so that we don't have + * to deal with any escaping or whatever. + */ +diff --git a/shared/util.go b/shared/util.go +index cdce360ee..b440093ce 100644 +--- a/shared/util.go ++++ b/shared/util.go +@@ -751,6 +751,11 @@ func IsBlockdevPath(pathName string) bool { + return ((fm&os.ModeDevice != 0) && (fm&os.ModeCharDevice == 0)) + } + ++// IsFileName checks if the given string is a valid file name (no "/", ".." or "\\"). ++func IsFileName(name string) bool { ++ return !strings.Contains(name, "/") && !strings.Contains(name, "\\") && !strings.Contains(name, "..") ++} ++ + // DeepCopy copies src to dest by using encoding/gob so its not that fast. + func DeepCopy(src, dest any) error { + buff := new(bytes.Buffer) diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/patches/101-CVE-2025-54287.patch lxd-5.0.2+git20231211.1364ae4/debian/patches/101-CVE-2025-54287.patch --- lxd-5.0.2+git20231211.1364ae4/debian/patches/101-CVE-2025-54287.patch 1970-01-01 00:00:00.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/patches/101-CVE-2025-54287.patch 2025-10-02 16:21:35.000000000 +0000 @@ -0,0 +1,36 @@ +From 2e8fc13caa89a7f4e999a6be17d6e9ecffe0d6d9 Mon Sep 17 00:00:00 2001 +From: Simon Deziel +Date: Wed, 25 Jun 2025 14:29:32 -0400 +Subject: [PATCH] shared/util: block some pongo2 functions in templates + +Signed-off-by: Simon Deziel +(cherry picked from commit a31f4534876e4f898db76a9938cc37f76b24ecd2) +--- + shared/util.go | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/shared/util.go b/shared/util.go +index cdce360ee..bfb51a73d 100644 +--- a/shared/util.go ++++ b/shared/util.go +@@ -1222,8 +1222,19 @@ func (r *ReadSeeker) Seek(offset int64, whence int) (int64, error) { + + // RenderTemplate renders a pongo2 template. + func RenderTemplate(template string, ctx pongo2.Context) (string, error) { ++ // Create custom TemplateSet ++ set := pongo2.NewSet("restricted", pongo2.DefaultLoader) ++ ++ // Ban tags that could be used to access the host's filesystem. ++ for _, tag := range []string{"extends", "import", "include", "ssi"} { ++ err := set.BanTag(tag) ++ if err != nil { ++ return "", fmt.Errorf("Failed to ban tag %q: %w", tag, err) ++ } ++ } ++ + // Load template from string +- tpl, err := pongo2.FromString("{% autoescape off %}" + template + "{% endautoescape %}") ++ tpl, err := set.FromString("{% autoescape off %}" + template + "{% endautoescape %}") + if err != nil { + return "", err + } diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/patches/102-CVE-2025-54288.patch lxd-5.0.2+git20231211.1364ae4/debian/patches/102-CVE-2025-54288.patch --- lxd-5.0.2+git20231211.1364ae4/debian/patches/102-CVE-2025-54288.patch 1970-01-01 00:00:00.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/patches/102-CVE-2025-54288.patch 2025-10-02 16:23:38.000000000 +0000 @@ -0,0 +1,35 @@ +From: Mathias Gibbens +Description: Backport fix for CVE-2025-54288 from Incus. The relevant commit in the 5.21-stable branch fixing the issue includes a lot of irrelevant refactoring, making a clean cherry-pick impossible. +Origin: https://github.com/lxc/incus/pull/2285 +Origin: https://github.com/canonical/lxd/commit/218aa9e81951a3616ee81b1ff23ec90d17f4d3c5 +Origin: https://github.com/canonical/lxd/security/advisories/GHSA-7232-97c6-j525 +diff --git a/lxd/devlxd.go b/lxd/devlxd.go +index b7ddff3fc..05230ee7f 100644 +--- a/lxd/devlxd.go ++++ b/lxd/devlxd.go +@@ -375,7 +375,12 @@ func findContainerForPid(pid int32, s *state.State) (instance.Container, error) + return nil, err + } + +- if strings.HasPrefix(string(cmdline), "[lxc monitor]") { ++ status, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) ++ if err != nil { ++ return nil, err ++ } ++ ++ if strings.HasPrefix(string(cmdline), "[lxc monitor]") && strings.Contains(string(status), fmt.Sprintf("NSpid: %d\n", pid)) { + // container names can't have spaces + parts := strings.Split(string(cmdline), " ") + name := strings.TrimSuffix(parts[len(parts)-1], "\x00") +@@ -399,11 +404,6 @@ func findContainerForPid(pid int32, s *state.State) (instance.Container, error) + return inst.(instance.Container), nil + } + +- status, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) +- if err != nil { +- return nil, err +- } +- + re, err := regexp.Compile(`^PPid:\s+([0-9]+)$`) + if err != nil { + return nil, err diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/patches/103a-CVE-2025-54286.patch lxd-5.0.2+git20231211.1364ae4/debian/patches/103a-CVE-2025-54286.patch --- lxd-5.0.2+git20231211.1364ae4/debian/patches/103a-CVE-2025-54286.patch 1970-01-01 00:00:00.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/patches/103a-CVE-2025-54286.patch 2025-10-02 16:21:35.000000000 +0000 @@ -0,0 +1,60 @@ +From e875d560331e4bf216a507235fddd1d47f5ceed4 Mon Sep 17 00:00:00 2001 +From: Thomas Parrott +Date: Mon, 30 Jun 2025 15:23:50 +0100 +Subject: [PATCH 1/2] lxd/daemon: Validate browser fetch metadata if supplied + to reject non-same-origin requests + +Signed-off-by: Thomas Parrott +(cherry picked from commit 35ac3922d60763c24b1474459c4401f7c8ed619b) +(cherry picked from commit 569b7d472b4fc1622579e0aed32dd445ba6f53d0) +--- + lxd/daemon.go | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/lxd/daemon.go b/lxd/daemon.go +index e9223817cb95..320841add92f 100644 +--- a/lxd/daemon.go ++++ b/lxd/daemon.go +@@ -652,6 +652,12 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) { + return response.NotImplemented(nil) + } + ++ // Protect against CSRF when using LXD-UI with browser that supports Fetch metadata. ++ // Deny Sec-Fetch-Site when set to cross-origin or same-site. ++ if shared.StringInSlice(r.Header.Get("Sec-Fetch-Site"), []string{"cross-origin", "same-site"}) { ++ return response.ErrorResponse(http.StatusForbidden, "Forbidden Sec-Fetch-Site header value") ++ } ++ + if action.AccessHandler != nil { + // Defer access control to custom handler + resp := action.AccessHandler(d, r) + +From bd99f6bd7ff0a9c1b43e02f2bbc3512f729582c7 Mon Sep 17 00:00:00 2001 +From: Thomas Parrott +Date: Mon, 30 Jun 2025 16:11:58 +0100 +Subject: [PATCH 2/2] test/suites/serverconfig: Check fetch metadata header is + validated + +Signed-off-by: Thomas Parrott +(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 30dd2a11f8cb..b62f30b5e00e 100644 +--- a/test/suites/serverconfig.sh ++++ b/test/suites/serverconfig.sh +@@ -35,6 +35,11 @@ test_server_config_access() { + # macaroons are also enabled + curl --unix-socket "$LXD_DIR/unix.socket" "lxd/1.0" | jq .metadata.auth_methods | grep candid + lxc config unset candid.api.url ++ ++ # test fetch metadata validation. ++ [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: same-origin' "lxd/1.0")" = "200" ] ++ [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: cross-origin' "lxd/1.0")" = "403" ] ++ [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: same-site' "lxd/1.0")" = "403" ] + } + + test_server_config_storage() { diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/patches/103b-CVE-2025-54286.patch lxd-5.0.2+git20231211.1364ae4/debian/patches/103b-CVE-2025-54286.patch --- lxd-5.0.2+git20231211.1364ae4/debian/patches/103b-CVE-2025-54286.patch 1970-01-01 00:00:00.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/patches/103b-CVE-2025-54286.patch 2025-10-02 16:23:38.000000000 +0000 @@ -0,0 +1,84 @@ +From 4975e0b9c927a97125ecc96a1496911ee68bfb28 Mon Sep 17 00:00:00 2001 +From: Thomas Parrott +Date: Fri, 4 Jul 2025 08:19:13 +0100 +Subject: [PATCH 1/3] lxd/daemon: Check for cross-site rather than invalid + cross-origin Sec-Fetch-Site header value + +Signed-off-by: Thomas Parrott +--- + lxd/daemon.go | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lxd/daemon.go b/lxd/daemon.go +index 320841add92f..59af7b9eecde 100644 +--- a/lxd/daemon.go ++++ b/lxd/daemon.go +@@ -653,8 +653,8 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) { + } + + // Protect against CSRF when using LXD-UI with browser that supports Fetch metadata. +- // Deny Sec-Fetch-Site when set to cross-origin or same-site. +- if shared.StringInSlice(r.Header.Get("Sec-Fetch-Site"), []string{"cross-origin", "same-site"}) { ++ // Deny Sec-Fetch-Site when set to cross-site or same-site. ++ if shared.StringInSlice(r.Header.Get("Sec-Fetch-Site"), []string{"cross-site", "same-site"}) { + return response.ErrorResponse(http.StatusForbidden, "Forbidden Sec-Fetch-Site header value") + } + + +From 45f93217de2f1bd21368b4e092a99e31d53bfaf9 Mon Sep 17 00:00:00 2001 +From: Thomas Parrott +Date: Fri, 4 Jul 2025 08:19:26 +0100 +Subject: [PATCH 2/3] test/suites/serverconfig: Update Sec-Fetch-Site tests + +Signed-off-by: Thomas Parrott +--- + test/suites/serverconfig.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/suites/serverconfig.sh b/test/suites/serverconfig.sh +index b62f30b5e00e..241f13cda0d3 100644 +--- a/test/suites/serverconfig.sh ++++ b/test/suites/serverconfig.sh +@@ -38,7 +38,7 @@ test_server_config_access() { + + # test fetch metadata validation. + [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: same-origin' "lxd/1.0")" = "200" ] +- [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: cross-origin' "lxd/1.0")" = "403" ] ++ [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: cross-site' "lxd/1.0")" = "403" ] + [ "$(curl --silent --unix-socket "$LXD_DIR/unix.socket" -w "%{http_code}" -o /dev/null -H 'Sec-Fetch-Site: same-site' "lxd/1.0")" = "403" ] + } + + +From 521fd8f118fe74cffa5e888fd19a513283250dd3 Mon Sep 17 00:00:00 2001 +From: Thomas Parrott +Date: Fri, 4 Jul 2025 08:20:11 +0100 +Subject: [PATCH 3/3] lxd/daemon: Define forbidden Sec-Fetch-Site values + +Signed-off-by: Thomas Parrott +--- + lxd/daemon.go | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lxd/daemon.go b/lxd/daemon.go +index 59af7b9eecde..b0b7c838f63d 100644 +--- a/lxd/daemon.go ++++ b/lxd/daemon.go +@@ -68,6 +68,9 @@ import ( + "github.com/canonical/lxd/shared/version" + ) + ++// secFetchSiteForbidden defines client Sec-Fetch-Site header values that will be forbidden access. ++var secFetchSiteForbidden = []string{"cross-site", "same-site"} ++ + // A Daemon can respond to requests from a shared client. + type Daemon struct { + clientCerts *certificate.Cache +@@ -654,7 +657,7 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) { + + // Protect against CSRF when using LXD-UI with browser that supports Fetch metadata. + // Deny Sec-Fetch-Site when set to cross-site or same-site. +- if shared.StringInSlice(r.Header.Get("Sec-Fetch-Site"), []string{"cross-site", "same-site"}) { ++ if shared.StringInSlice(r.Header.Get("Sec-Fetch-Site"), secFetchSiteForbidden) { + return response.ErrorResponse(http.StatusForbidden, "Forbidden Sec-Fetch-Site header value") + } + diff -Nru lxd-5.0.2+git20231211.1364ae4/debian/patches/series lxd-5.0.2+git20231211.1364ae4/debian/patches/series --- lxd-5.0.2+git20231211.1364ae4/debian/patches/series 2025-02-23 21:03:50.000000000 +0000 +++ lxd-5.0.2+git20231211.1364ae4/debian/patches/series 2025-10-02 16:23:38.000000000 +0000 @@ -9,3 +9,8 @@ 010-cherry-pick-update-test-cert.patch 011-newer-qemu-fixes.patch 012-fix-issues-with-old-nvram.patch +100-CVE-2025-54293.patch +101-CVE-2025-54287.patch +102-CVE-2025-54288.patch +103a-CVE-2025-54286.patch +103b-CVE-2025-54286.patch