Your message dated Sat, 12 Sep 2026 08:05:41 +0000
with message-id <[email protected]>
and subject line Released in 13.7
has caused the Debian Bug report #1146498,
regarding trixie-pu: package incus/6.0.4-2+deb13u10
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1146498: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1146498
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: trixie
User: [email protected]
Usertags: pu
X-Debbugs-Cc: [email protected], [email protected]
Control: affects -1 + src:incus

[ Reason ]
Last week's release of Incus 7.4 included fixes for two moderate
severity issues, CVE-2026-81500 and CVE-2026-81501. After discussion
with the Security Team, these vulnerabilities won't receive their own
DSA, but will be addressed via the upcoming point release.

[ Impact ]
Incus in trixie is currently vulnerable to CVE-2026-81500 and CVE-2026-
81501.

[ Tests ]
None -- both security issues are somewhat obscure edge cases, but the
fixes have been in the stable release for a week now and no regressions
have been reported upstream.

[ Risks ]
Minor/none -- two targeted fixes cherry-picked from the upstream git
repo.

[ Checklist ]
  [*] *all* changes are documented in the d/changelog
  [*] I reviewed all changes and I approve them
  [*] attach debdiff against the package in (old)stable
  [*] the issue is verified as fixed in unstable

[ Changes ]
Two security fixes as outlined above. Also updated d/changelog with
missing CVEs that hadn't been assigned by GitHub when the previous
release was uploaded.

[ Other info ]
The source debdiff is attached.
diff --git a/debian/changelog b/debian/changelog
index 438c618e46..8cc80a7c1f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+incus (6.0.4-2+deb13u10) trixie; urgency=medium
+
+  * Cherry-pick fixes for the following security issues
+    - CVE-2026-81500 / GHSA-9pqw-c7m4-xvg7
+    - CVE-2026-81501 / GHSA-c6wx-8679-hpr9
+
+ -- Mathias Gibbens <[email protected]>  Wed, 02 Sep 2026 16:39:29 +0000
+
 incus (6.0.4-2+deb13u9) trixie-security; urgency=high
 
   * Cherry-pick upstream fix for large nft ruleset performance
@@ -8,11 +16,11 @@ incus (6.0.4-2+deb13u9) trixie-security; urgency=high
     - CVE-2026-62941 / GHSA-mq9x-prm8-3vpw
     - CVE-2026-63125 / GHSA-6rqx-22hc-qm36
     - CVE-2026-63343 / GHSA-fmjx-5j3g-997p
-    - GHSA-26gp-p5fw-3r2h
-    - GHSA-4qxq-p5hm-3q3p
-    - GHSA-67qw-68v3-36h6
-    - GHSA-m3j6-p3v3-qmjv
-    - GHSA-p2v3-6wvc-cv3p
+    - CVE-2026-81493 / GHSA-p2v3-6wvc-cv3p
+    - CVE-2026-81495 / GHSA-67qw-68v3-36h6
+    - CVE-2026-81496 / GHSA-26gp-p5fw-3r2h
+    - CVE-2026-81497 / GHSA-4qxq-p5hm-3q3p
+    - CVE-2026-81498 / GHSA-m3j6-p3v3-qmjv
   * Cherry-pick four additional security fixes not assigned CVEs
 
  -- Mathias Gibbens <[email protected]>  Thu, 30 Jul 2026 22:57:51 +0000
diff --git a/debian/patches/147-CVE-2026-81500.patch b/debian/patches/147-CVE-2026-81500.patch
new file mode 100644
index 0000000000..217f0de519
--- /dev/null
+++ b/debian/patches/147-CVE-2026-81500.patch
@@ -0,0 +1,91 @@
+From d4d7badf6597274320b78575e77aec5720163c9c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
+Date: Sun, 23 Aug 2026 17:26:26 -0400
+Subject: [PATCH] client/images: Prevent path traversal in downloaded image
+ name
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The local filename for an exported image came from server-controlled
+data (Content-Disposition for unified images, the simplestreams index
+path) and was joined with the target directory. Basename it.
+
+This addresses GHSA-9pqw-c7m4-xvg7 (CVE pending)
+
+Signed-off-by: Stéphane Graber <[email protected]>
+Rebased-by: Mathias Gibbens <[email protected]>
+---
+ client/incus_images.go         |  4 +++-
+ client/simplestreams_images.go | 13 +++++++------
+ 2 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/client/incus_images.go b/client/incus_images.go
+index ed48d08be..3a0afccb2 100644
+--- a/client/incus_images.go
++++ b/client/incus_images.go
+@@ -9,6 +9,7 @@ import (
+ 	"net/http"
+ 	"net/url"
+ 	"os"
++	"path/filepath"
+ 	"slices"
+ 	"strings"
+ 	"time"
+@@ -325,7 +326,8 @@ func incusDownloadImage(fingerprint string, uri string, userAgent string, do fun
+ 	}
+ 
+ 	resp.MetaSize = size
+-	resp.MetaName = filename
++	// Basename the server-provided name to prevent path traversal.
++	resp.MetaName = filepath.Base(filename)
+ 
+ 	// Check the hash
+ 	hash := fmt.Sprintf("%x", sha256.Sum(nil))
+diff --git a/client/simplestreams_images.go b/client/simplestreams_images.go
+index 00cc35409..6bbfbe9d4 100644
+--- a/client/simplestreams_images.go
++++ b/client/simplestreams_images.go
+@@ -10,6 +10,7 @@ import (
+ 	"net/url"
+ 	"os"
+ 	"os/exec"
++	"path/filepath"
+ 	"strings"
+ 	"time"
+ 
+@@ -143,8 +144,8 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
+ 			return nil, err
+ 		}
+ 
+-		parts := strings.Split(meta.Path, "/")
+-		resp.MetaName = parts[len(parts)-1]
++		// Basename the server-provided name to prevent path traversal.
++		resp.MetaName = filepath.Base(meta.Path)
+ 		resp.MetaSize = size
+ 	}
+ 
+@@ -205,8 +206,8 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
+ 					return nil, err
+ 				}
+ 
+-				parts := strings.Split(rootfs.Path, "/")
+-				resp.RootfsName = parts[len(parts)-1]
++				// Basename the server-provided name to prevent path traversal.
++				resp.RootfsName = filepath.Base(rootfs.Path)
+ 				resp.RootfsSize = size
+ 				downloaded = true
+ 			}
+@@ -219,8 +220,8 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
+ 				return nil, err
+ 			}
+ 
+-			parts := strings.Split(rootfs.Path, "/")
+-			resp.RootfsName = parts[len(parts)-1]
++			// Basename the server-provided name to prevent path traversal.
++			resp.RootfsName = filepath.Base(rootfs.Path)
+ 			resp.RootfsSize = size
+ 		}
+ 	}
+-- 
+2.47.3
diff --git a/debian/patches/148-CVE-2026-81501.patch b/debian/patches/148-CVE-2026-81501.patch
new file mode 100644
index 0000000000..f05a56fb8b
--- /dev/null
+++ b/debian/patches/148-CVE-2026-81501.patch
@@ -0,0 +1,115 @@
+From a04abf23169d0597a544c6d96044a0f7aa9f19bf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
+Date: Sun, 23 Aug 2026 17:26:26 -0400
+Subject: [PATCH] incusd/images: Check access before reusing cross-project
+ image
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+imageDownload reused an image from another project without checking the
+caller could view it, letting a client that knew a private fingerprint
+import it. Only reuse it directly when public or viewable, otherwise
+download it (proving access) and dedupe against the on-disk copy.
+
+This addresses GHSA-c6wx-8679-hpr9 (CVE pending)
+
+Signed-off-by: Stéphane Graber <[email protected]>
+Rebased-by: Mathias Gibbens <[email protected]>
+---
+ cmd/incusd/daemon_images.go  | 38 +++++++++++++++++++++++++++++++-----
+ internal/server/db/images.go |  1 +
+ 2 files changed, 34 insertions(+), 5 deletions(-)
+
+diff --git a/cmd/incusd/daemon_images.go b/cmd/incusd/daemon_images.go
+index 8eafb6de4..c26e1540e 100644
+--- a/cmd/incusd/daemon_images.go
++++ b/cmd/incusd/daemon_images.go
+@@ -14,6 +14,7 @@ import (
+ 
+ 	incus "github.com/lxc/incus/v6/client"
+ 	internalIO "github.com/lxc/incus/v6/internal/io"
++	"github.com/lxc/incus/v6/internal/server/auth"
+ 	"github.com/lxc/incus/v6/internal/server/db"
+ 	"github.com/lxc/incus/v6/internal/server/db/cluster"
+ 	"github.com/lxc/incus/v6/internal/server/locking"
+@@ -195,13 +196,37 @@ func ImageDownload(ctx context.Context, r *http.Request, s *state.State, op *ope
+ 			}
+ 		}
+ 	} else if response.IsNotFoundError(err) {
++		var otherImg *api.Image
+ 		err = s.DB.Cluster.Transaction(ctx, func(ctx context.Context, tx *db.ClusterTx) error {
+ 			// Check if the image already exists in some other project.
+-			_, imgInfo, err = tx.GetImageFromAnyProject(ctx, fp)
++			_, otherImg, err = tx.GetImageFromAnyProject(ctx, fp)
+ 
+ 			return err
+ 		})
+ 		if err == nil {
++			// Only reuse another project's image when the caller may see it,
++			// otherwise download it (proving access) and dedupe on disk.
++			reuse := otherImg.Public || r == nil
++			if !reuse {
++				err = s.Authorizer.CheckPermission(ctx, r, auth.ObjectImage(otherImg.Project, otherImg.Fingerprint), auth.EntitlementCanView)
++				if err == nil {
++					reuse = true
++				} else if !api.StatusErrorCheck(err, http.StatusForbidden) {
++					return nil, false, err
++				}
++
++				err = nil
++			}
++
++			if reuse {
++				imgInfo = otherImg
++			} else if args.Server == "" {
++				// No source to prove access against.
++				return nil, false, api.StatusErrorf(http.StatusNotFound, "Image not found")
++			}
++		}
++
++		if err == nil && imgInfo != nil {
+ 			var nodeAddress string
+ 
+ 			err = s.DB.Cluster.Transaction(ctx, func(ctx context.Context, tx *db.ClusterTx) error {
+@@ -317,9 +342,9 @@ func ImageDownload(ctx context.Context, r *http.Request, s *state.State, op *ope
+ 		return nil, false, fmt.Errorf("Invalid image fingerprint")
+ 	}
+ 
+-	// Cleanup any leftover from a past attempt
++	// Download to a temporary name so an existing on-disk copy isn't overwritten.
+ 	destDir := internalUtil.VarPath("images")
+-	destName := filepath.Join(destDir, fp)
++	destName := filepath.Join(destDir, fp+".download")
+ 
+ 	failure := true
+ 	cleanup := func() {
+@@ -576,9 +601,12 @@ func ImageDownload(ctx context.Context, r *http.Request, s *state.State, op *ope
+ 		return nil, false, fmt.Errorf("Invalid image fingerprint")
+ 	}
+ 
+-	// Check if the image path changed (private images)
++	// Reuse an existing on-disk copy if present, otherwise move ours into place.
+ 	newDestName := filepath.Join(destDir, fp)
+-	if newDestName != destName {
++	if util.PathExists(newDestName) {
++		_ = os.Remove(destName)
++		_ = os.Remove(destName + ".rootfs")
++	} else {
+ 		err = internalUtil.FileMove(destName, newDestName)
+ 		if err != nil {
+ 			return nil, false, err
+diff --git a/internal/server/db/images.go b/internal/server/db/images.go
+index 2a730e596..b3719becf 100644
+--- a/internal/server/db/images.go
++++ b/internal/server/db/images.go
+@@ -436,6 +436,7 @@ func (c *ClusterTx) GetImageFromAnyProject(ctx context.Context, fingerprint stri
+ 
+ 	object = images[0]
+ 
++	image.Project = object.Project
+ 	image.Fingerprint = object.Fingerprint
+ 	image.Filename = object.Filename
+ 	image.Size = object.Size
+-- 
+2.47.3
diff --git a/debian/patches/series b/debian/patches/series
index 45d2cab03b..f04af2fc4f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -54,3 +54,5 @@
 144-GHSA-m3j6-p3v3-qmjv.patch
 145-GHSA-p2v3-6wvc-cv3p.patch
 146-incus-7.3-fixes.patch
+147-CVE-2026-81500.patch
+148-CVE-2026-81501.patch

Attachment: signature.asc
Description: This is a digitally signed message part


--- End Message ---
--- Begin Message ---
Version: 13.7

This update was released as part of 13.7.

--- End Message ---

Reply via email to