VYPR
High severityNVD Advisory· Published Mar 26, 2026· Updated Mar 30, 2026

Incus does not verify combined fingerprint when downloading images from simplestreams servers

CVE-2026-33542

Description

Incus is a system container and virtual machine manager. Prior to version 6.23.0, a lack of validation of the image fingerprint when downloading from simplestreams image servers opens the door to image cache poisoning and under very narrow circumstances exposes other tenants to running attacker controlled images rather than the expected one. Version 6.23.0 patches the issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/lxc/incus/v6/clientGo
< 6.23.06.23.0

Affected products

1

Patches

4
04e97418189f

client/simplestreams: Validate the full image hash

https://github.com/lxc/incusStéphane GraberMar 23, 2026via ghsa
1 file changed · +46 0
  • client/simplestreams_images.go+46 0 modified
    @@ -97,6 +97,14 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
     	httpTransport.ResponseHeaderTimeout = 30 * time.Second
     	httpClient.Transport = httpTransport
     
    +	// Get the image and expand the fingerprint.
    +	image, err := r.ssClient.GetImage(fingerprint)
    +	if err != nil {
    +		return nil, err
    +	}
    +
    +	fingerprint = image.Fingerprint
    +
     	// Get the file list
     	files, err := r.ssClient.GetFiles(fingerprint)
     	if err != nil {
    @@ -240,6 +248,44 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
     		}
     	}
     
    +	// Validate the full image hash.
    +	//
    +	// Normally we'd do that as we download the image to avoid having to
    +	// re-read the data, but because the simplestreams allows retries (HTTP to HTTPS),
    +	// we don't have a clean reader that can be used for that.
    +	//
    +	// Another situation where we couldn't do a streaming hash anyway is when processing delta images.
    +	hash256 := sha256.New()
    +
    +	if resp.MetaSize > 0 && req.MetaFile != nil {
    +		_, err = req.MetaFile.Seek(0, io.SeekStart)
    +		if err != nil {
    +			return nil, err
    +		}
    +
    +		_, err := io.Copy(hash256, req.MetaFile)
    +		if err != nil {
    +			return nil, err
    +		}
    +	}
    +
    +	if resp.RootfsSize > 0 && req.RootfsFile != nil {
    +		_, err = req.RootfsFile.Seek(0, io.SeekStart)
    +		if err != nil {
    +			return nil, err
    +		}
    +
    +		_, err := io.Copy(hash256, req.RootfsFile)
    +		if err != nil {
    +			return nil, err
    +		}
    +	}
    +
    +	hash := fmt.Sprintf("%x", hash256.Sum(nil))
    +	if hash != fingerprint {
    +		return nil, fmt.Errorf("Image fingerprint doesn't match. Got %s expected %s", hash, fingerprint)
    +	}
    +
     	return &resp, nil
     }
     
    
72688b7d9400

incusd: Update for changes to incus.ImageFileRequest

https://github.com/lxc/incusStéphane GraberMar 23, 2026via ghsa
2 files changed · +4 4
  • cmd/incusd/daemon_images.go+2 2 modified
    @@ -412,8 +412,8 @@ func ImageDownload(ctx context.Context, r *http.Request, s *state.State, op *ope
     		// Download the image
     		var resp *incus.ImageFileResponse
     		request := incus.ImageFileRequest{
    -			MetaFile:        io.WriteSeeker(dest),
    -			RootfsFile:      io.WriteSeeker(destRootfs),
    +			MetaFile:        io.ReadWriteSeeker(dest),
    +			RootfsFile:      io.ReadWriteSeeker(destRootfs),
     			ProgressHandler: progress,
     			Canceler:        canceler,
     			DeltaSourceRetriever: func(fingerprint string, file string) string {
    
  • cmd/incusd/images.go+2 2 modified
    @@ -4555,8 +4555,8 @@ func imageImportFromNode(imagesDir string, client incus.InstanceServer, fingerpr
     	defer func() { _ = rootfsFile.Close() }()
     
     	getReq := incus.ImageFileRequest{
    -		MetaFile:   io.WriteSeeker(metaFile),
    -		RootfsFile: io.WriteSeeker(rootfsFile),
    +		MetaFile:   io.ReadWriteSeeker(metaFile),
    +		RootfsFile: io.ReadWriteSeeker(rootfsFile),
     	}
     
     	getResp, err := client.GetImageFile(fingerprint, getReq)
    
4a80447c52d6

incus: Update for changes to incus.ImageFileRequest

https://github.com/lxc/incusStéphane GraberMar 23, 2026via ghsa
1 file changed · +2 2
  • cmd/incus/image.go+2 2 modified
    @@ -576,8 +576,8 @@ func (c *cmdImageExport) Run(cmd *cobra.Command, args []string) error {
     	}
     
     	req := incus.ImageFileRequest{
    -		MetaFile:        io.WriteSeeker(dest),
    -		RootfsFile:      io.WriteSeeker(destRootfs),
    +		MetaFile:        io.ReadWriteSeeker(dest),
    +		RootfsFile:      io.ReadWriteSeeker(destRootfs),
     		ProgressHandler: progress.UpdateProgress,
     	}
     
    
ee26f72524ab

client: Make ImageFileRequest require a ReadWriteSeeker

https://github.com/lxc/incusStéphane GraberMar 23, 2026via ghsa
1 file changed · +2 2
  • client/interfaces.go+2 2 modified
    @@ -502,10 +502,10 @@ type ImageCreateArgs struct {
     // The ImageFileRequest struct is used for an image download request.
     type ImageFileRequest struct {
     	// Writer for the metadata file
    -	MetaFile io.WriteSeeker
    +	MetaFile io.ReadWriteSeeker
     
     	// Writer for the rootfs file
    -	RootfsFile io.WriteSeeker
    +	RootfsFile io.ReadWriteSeeker
     
     	// Progress handler (called whenever some progress is made)
     	ProgressHandler func(progress ioprogress.ProgressData)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.