Skip to main content
CVE-2026-48754VulnerabilityPublished

createDependentVolumesFromBackup · Incus: Nil-pointer dereference

Affects github.com/lxc/incus/v7/cmd/incusdSource GCVE Database

0

Mentioned vulnerabilities

Authoritative record:CVE-2026-48754· Low 2.1

Public exploit available · CVSS 2.1 Low : upgrade to 7.1.0 as a priority.

Data as of 26 Oct 2026, 14:05 UTC

CVSS 4.0 base score
2.1Low
How severe the flaw is on the 0–10 CVSS scale.
EPSS
0.3% chance of exploitation in 30 days – higher than 31% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
Patch
Available – fixed in 7.1.0
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P

Exploitation evidence

t = 0 is the CVE’s publication on cve.org

  1. Disclosed: evidence found.

    CVE published 21 Aug 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponised: evidence found.

    CISA SSVC: proof of concept public

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

Timeline

  1. CVE ID reserved

    by GitHub, Inc.

    , 91 days before disclosure

  2. CVE published

    on cve.org

    , t = 0

  3. CISA SSVC assessment

    proof of concept public

    , 5 days after disclosure

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), CISA SSVC, the Metasploit, Exploit-DB and nuclei-templates index as of 26 Oct 2026.

What to do

Upgrade github.com/lxc/incus/v7/cmd/incusd to 7.1.0.

Affected software

ProductAffectedFixed in
Gogithub.com/lxc/incus/v7/cmd/incusdAffected
  • <7.1.0
Fixed in
  • 7.1.0

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

## Summary `(*backend).createDependentVolumesFromBackup` in [`internal/server/storage/backend.go`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/internal/server/storage/backend.go) contains a cluster of unguarded pointer derefs on every dependent-volume entry's `VolumeSnapshots[i]`, `Volume`, and `Pool` sub-fields. An authenticated user with `can_create_instances` permission on any project can crash the `incusd` daemon by uploading an instance backup tarball whose `dependent_volumes[*]` block contains a nil snapshot pointer (or omits `volume:` / `pool:`). This is a sibling-field variant of the 2026-05-04 batch fix `d768f81c0a1d985f35ae56219519822b080bf5e3` ("Properly check dependent volumes on import"). That commit added `if disk == nil` at the top of the outer loop, but did not guard the four sub-pointer fields the loop body dereferences naked. ## Vulnerable code [`internal/server/storage/backend.go:9352-9412`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/internal/server/storage/backend.go#L9352-L9412): ```go func (b *backend) createDependentVolumesFromBackup(srcBackup backup.Info, ...) error { ... for _, disk := range srcBackup.Config.DependentVolumes { if disk == nil { // ← d768f81 parent fix return errors.New("Bad dependent volume definition found in index") } ... snapshots := []string{} for _, snap := range disk.VolumeSnapshots { snapshots = append(snapshots, snap.Name) // ← I-2 trigger: snap may be nil } bInfo := backup.Info{ Project: disk.Volume.Project, // ← disk.Volume may be nil Name: disk.Volume.Name, Backend: disk.Pool.Driver, // ← disk.Pool may be nil Pool: disk.Pool.Name, ... } ... devKey := fmt.Sprintf("%s/%s", disk.Pool.Name, disk.Volume.Name) ... } } ``` `disk` has type `*config.Config` (declared in [`internal/server/backup/config/backup_config.go:8`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/internal/server/backup/config/backup_config.go#L8)). Its `Volume` field is `*api.StorageVolume`, `Pool` is `*api.StoragePool`, `VolumeSnapshots` is `[]*api.StorageVolumeSnapshot` — all yaml `omitempty`. YAML omission decodes to nil for each. The parent fix mental-modeled "outer-iteration variable nil"; it did not walk every sub-field deref inside the loop body. Direct asymmetric-guard variant. ## Reach 1. Attacker is an authenticated client with `can_create_instances` on any project. Same auth gate as GHSA-8g7m-96c8-8wwc / CVE-2026-47753. 2. `POST /1.0/instances` with `Content-Type: application/octet-stream` and `X-Incus-name: <name>`. 3. Body is a tar containing [`backup/index.yaml`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/backup/index.yaml) whose `config:` block has a non-nil `container:` (passes `instances_post.go:854 if bInfo.Config == nil || bInfo.Config.Container == nil`) and a `dependent_volumes:` list with a malformed entry. 4. Chain: `instancesPost` -> `createFromBackup:854` (Container guard passes) -> `pool.CreateInstanceFromBackup` -> `backend.go:782 b.createDependentVolumesFromBackup` -> `backend.go:9374 snap.Name` panics on the nil `*api.StorageVolumeSnapshot` element. 5. `incusd` dies. Persistent DoS on repeat. Minimal [`backup/index.yaml`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/backup/index.yaml) (used in the bundled PoC): ```yaml name: poc-inst backend: dir pool: default type: container optimized: false optimized_header: false snapshots: [] config: container: name: poc-inst architecture: x86_64 type: container profiles: ["default"] config: {} devices: {} expanded_devices: depdisk: {type: disk, dependent: "true", pool: default, source: depvol, path: /data} expanded_config: {} dependent_volumes: - volume: {name: depvol, type: custom, content_type: filesystem, config: {}} pool: {name: default, driver: dir, config: {}} volume_snapshots: - ~ # explicit null entry → snap.Name at 9374 panics ``` (The container block must declare at least one device with `type: disk`, `dependent: "true"`, `pool != ""`, `path != "/"` to populate `devicesMap` and reach the second loop. Trivially satisfiable.) An equivalent triggering YAML omits `volume:` or `pool:` from the dependent_volumes entry; in that case `disk.Volume.Project` at 9378 panics instead. ## Proof of concept (end-to-end against running daemon) Bundled in the report: `make_backup.sh` + 666-byte `poc-inst.tar.gz`. Tested against `incus 7.0.0` (zabbly latest GA, build `1:0~ubuntu24.04~202605201355`) inside a privileged Ubuntu 24.04 container with default `dir` pool. ```bash $ curl -s --unix-socket /var/lib/incus/unix.socket -

References

Community reviews

Loading reviews…