🛡️ CVE-2026-40251 — incus
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
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
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 |
References
Similar Threats
- Medium CVE-2026-35527
- High CVE-2026-40195
- High CVE-2026-40197
- Medium CVE-2026-40243
- Medium CVE-2026-41647
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
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.