High severity8.2NVD Advisory· Published Feb 18, 2026· Updated Apr 15, 2026
CVE-2026-24708
CVE-2026-24708
Description
An issue was discovered in OpenStack Nova before 30.2.2, 31 before 31.2.1, and 32 before 32.1.1. By writing a malicious QCOW header to a root or ephemeral disk and then triggering a resize, a user may convince Nova's Flat image backend to call qemu-img without a format restriction, resulting in an unsafe image resize operation that could destroy data on the host system. Only compute nodes using the Flat image backend (usually configured with use_cow_images=False) are affected.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
NovaPyPI | >= 32.0.0.0rc1, <= 32.1.0 | — |
NovaPyPI | >= 31.0.0.0rc1, <= 31.2.0 | — |
NovaPyPI | <= 30.2.1 | — |
Patches
13eba22ff09c8Make disk.extend() pass format to qemu-img
2 files changed · +46 −5
nova/tests/unit/virt/disk/test_api.py+31 −4 modified@@ -19,6 +19,7 @@ from oslo_concurrency import processutils from oslo_utils import units +from nova import exception from nova import test from nova.virt.disk import api from nova.virt.disk.mount import api as mount @@ -128,7 +129,7 @@ def test_extend_qcow_success(self, mock_exec, mock_inst, mock_resize, mock_can_resize.assert_called_once_with(imgfile, imgsize) mock_exec.assert_called_once_with('qemu-img', 'resize', - imgfile, imgsize) + '-f', 'qcow2', imgfile, imgsize) mock_extendable.assert_called_once_with(image) mock_inst.assert_called_once_with(image, None, None) mock_resize.assert_called_once_with(mounter.device, @@ -154,8 +155,8 @@ def test_extend_qcow_no_resize(self, mock_execute, mock_extendable, api.extend(image, imgsize) mock_can_resize_image.assert_called_once_with(imgfile, imgsize) - mock_execute.assert_called_once_with('qemu-img', 'resize', imgfile, - imgsize) + mock_execute.assert_called_once_with('qemu-img', 'resize', '-f', + 'qcow2', imgfile, imgsize) self.assertFalse(mock_extendable.called) @mock.patch.object(api, 'can_resize_image', autospec=True, @@ -186,8 +187,34 @@ def test_extend_raw_success(self, mock_exec, mock_resize, api.extend(image, imgsize) mock_exec.assert_has_calls( - [mock.call('qemu-img', 'resize', imgfile, imgsize), + [mock.call('qemu-img', 'resize', '-f', 'raw', imgfile, imgsize), mock.call('e2label', image.path)]) mock_resize.assert_called_once_with(imgfile, run_as_root=False, check_exit_code=[0]) mock_can_resize.assert_called_once_with(imgfile, imgsize) + + @mock.patch.object(api, 'can_resize_image', autospec=True, + return_value=True) + @mock.patch.object(api, 'resize2fs', autospec=True) + @mock.patch('oslo_concurrency.processutils.execute', autospec=True) + def test_extend_vmdk_failure(self, mock_exec, mock_resize, + mock_can_resize): + + imgfile = tempfile.NamedTemporaryFile() + self.addCleanup(imgfile.close) + imgsize = 10 + # NOTE(danms): There is no image.model.FORMAT_VMDK, but since the + # code initializes this directly from Image.disk_format without using + # the constant (tsk), this can actually happen at runtime. + self.assertRaises(exception.InvalidImageFormat, + imgmodel.LocalFileImage, imgfile, 'vmdk') + + # Patch ALL_FORMATS to include vmdk as if it got added at some point + with mock.patch('nova.virt.image.model.ALL_FORMATS', + new=['vmdk']): + image = imgmodel.LocalFileImage(imgfile, 'vmdk') + + # Make sure that we still don't call qemu-img resize on the image + self.assertRaises(exception.InvalidDiskFormat, + api.extend, image, imgsize) + mock_exec.assert_not_called()
nova/virt/disk/api.py+15 −1 modified@@ -123,7 +123,21 @@ def extend(image, size): nova.privsep.libvirt.ploop_resize(image.path, size) return - processutils.execute('qemu-img', 'resize', image.path, size) + # NOTE(danms): We should not call qemu-img without a format, and + # only qcow2 and raw are supported. So check which one we're being + # told this is supposed to be and pass that to qemu-img. Also note + # that we need to pass the qemu format string to this command, which + # may or may not be the same as the FORMAT_* constant, so be + # explicit here. + if image.format == imgmodel.FORMAT_RAW: + format = 'raw' + elif image.format == imgmodel.FORMAT_QCOW2: + format = 'qcow2' + else: + LOG.warning('Attempting to resize image %s with format %s, ' + 'which is not supported', image.path, image.format) + raise exception.InvalidDiskFormat(disk_format=image.format) + processutils.execute('qemu-img', 'resize', '-f', format, image.path, size) if (image.format != imgmodel.FORMAT_RAW and not CONF.resize_fs_using_block_device):
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-m4f3-qp2w-gwh6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-24708ghsaADVISORY
- bugs.launchpad.net/nova/+bug/2137507nvdWEB
- github.com/openstack/nova/commit/3eba22ff09c81a61750fbb4882e5f1f01a20fdf5ghsaWEB
- lists.debian.org/debian-lts-announce/2026/02/msg00025.htmlnvdWEB
- www.openwall.com/lists/oss-security/2026/02/17/7nvdWEB
News mentions
0No linked articles in our index yet.