🛡️ CVE-2026-40251 — incus

🟠 CVSS 8.0 — High ✅ No Known Exploit NVD
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Incus Vulnerable to Panic via Snapshot Bounds Check

Summary

Missing validation logic in the storage volume import logic allows an authenticated user with access to Incus' storage volume feature to cause the Incus daemon to crash. Repeated use of this issue can be used to keep Incus offline causing a denial of service.

Details

The backup restore subsystem contains an out-of-bounds panic vulnerability caused by an invalid bounds check when indexing snapshot metadata arrays. The same flawed pattern also appears in the migration path.

When iterating through physical snapshots provided in a backup archive, the loop uses the index i to look up corresponding metadata in the parsed Config.Snapshots and Config.VolumeSnapshots slices. To ensure that the metadata slice is long enough, the code uses the guard condition len(slice) >= i-1. This check is incorrect because it can still evaluate to true when the subsequent slice[i] access is out of bounds, including when i >= len(slice), triggering a runtime panic.

An attacker can trigger this by submitting a backup archive that contains physical snapshot directories, which drive the loop variable i, while supplying a tampered index.yaml with an empty or truncated snapshot metadata array. This causes the daemon to index beyond the end of the metadata slice and crash, resulting in immediate denial of service on the node.

Affected File:

https://github.com/lxc/incus/blob/v6.22.0/internal/server/storage/backend.go

Affected Code:

```

func (b *backend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(instance.Instance) error, revert.Hook, error) {

[...]

postHook := func(inst instance.Instance) error {

[...]

for i, backupFileSnap := range srcBackup.Snapshots {

var volumeSnapDescription string

var volumeSnapConfig map[string]string

var volumeSnapExpiryDate time.Time

var volumeSnapCreationDate time.Time

// Check if snapshot volume config is available for restore and matches snapshot name.

if srcBackup.Config != nil {

if len(srcBackup.Config.Snapshots) >= i-1 && srcBackup.Config.Snapshots[i] != nil && srcBackup.Config.Snapshots[i].Name == backupFileSnap {

// Use instance snapshot's creation date if snap info available.

volumeSnapCreationDate = srcBackup.Config.Snapshots[i].CreatedAt

}

if len(srcBackup.Config.VolumeSnapshots) >= i-1 && srcBackup.Config.VolumeSnapshots[i] != nil && srcBackup.Config.VolumeSnapshots[i].Name == backupFileSnap {

// If the backup restore interface provides volume snapshot config use it,

// otherwise use default volume config for the storage pool.

volumeSnapDescription = srcBackup.Config.VolumeSnapshots[i].Description

volumeSnapConfig = srcBackup.Config.VolumeSnapshots[i].Config

if srcBackup.Config.VolumeSnapshots[i].ExpiresAt != nil {

volumeSnapExpiryDate = *srcBackup.Config.VolumeSnapshots[i].ExpiresAt

}

// Use volume's creation date if available.

if !srcBackup.Config.VolumeSnapshots[i].CreatedAt.IsZero() {

volumeSnapCreationDate = srcBackup.Config.VolumeSnapshots[i].CreatedAt

}

}

}

[...]

}

[...]

}

[...]

}

[...]

func (b *backend) CreateInstanceFromMigration(inst instance.Instance, conn io.ReadWriteCloser, args localMigration.VolumeTargetArgs, op *operations.Operation) error {

[...]

if !isRemoteClusterMove || args.StoragePool != "" {

for i, snapshot := range args.Snapshots {

snapName := snapshot.GetName()

newSnapshotName := drivers.GetSnapshotVolumeName(inst.Name(), snapName)

snapConfig := vol.Config() // Use parent volume config by default.

snapDescription := volumeDescription // Use parent volume description by default.

snapExpiryDate := time.Time{}

snapCreationDate := time.Time{}

// If the source snapshot config is available, use that.

if srcInfo != nil && srcInfo.Config != nil {

if len(srcInfo.Config.Snapshots) >= i-1 && srcInfo.Config.Snapshots[i] != nil && srcInfo.Config.Snapshots[i].Name == snapName {

// Use instance snapshot's creation date if snap info available.

snapCreationDate = srcInfo.Config.Snapshots[i].CreatedAt

}

if len(srcInfo.Config.VolumeSnapshots) >= i-1 && srcInfo.Config.VolumeSnapshots[i] != nil && srcInfo.Config.VolumeSnapshots[i].Name == snapName {

// Check if snapshot volume config is available then use it.

snapDescription = srcInfo.Config.Vol

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality none, integrity none, availability high.

Affected software

CVE-2026-40251 is recorded against 5 packages.

  • github.com/lxc/incus
  • github.com/lxc/incus/v6
  • github.com/lxc/incus/v6/cmd/incusd
  • github.com/lxc/incus/v7
  • incus (fixed in 7.0.0)

Timeline and source

Published on 25 June 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Advisory)
nvd.nist.gov (Advisory)
github.com (Web)

CVE-2026-40251 on other distributions

Each distribution ships its own build and its own fixed version. Pick the one you run:

Details

Severity High
CVSS Score 8.0
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
CWE N/A
Public Exploit ✅ No
Source NVD
Published 2026-06-25
Updated 2026-08-12
Modified 2026-06-25
Fix URL N/A

Affected Packages

Software From version Fixed in
github.com/lxc/incus
github.com/lxc/incus/v6
github.com/lxc/incus/v6/cmd/incusd
github.com/lxc/incus/v7
incus 7.0.0

Similar Threats

Site Security Check

Is incus part of your stack?

CVE-2026-40251 is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.