{"schema":"threatline.record/2","record":{"id":"CVE-2026-112405","aliases":["GHSA-cp9v-662q-vvx9"],"summary":"Pillow: NULL pointer dereference in Image.merge via an unvalidated band 0","details":"### Summary\n`Image.merge()` checks the mode of every input band except band 0. If band 0 is a single-band `I` or `F` image, the native merge routine reads a pixel pointer that is NULL for those modes and the process crashes. The IPTC plugin reaches this from a plain `Image.open()` followed by a load, and IPTC has no magic-byte prefilter, so a crafted file with no recognizable header can drive it.\n\n### Details\nThe validation loop skips band 0:\n\n- `src/PIL/Image.py:3795` iterates `for band in bands[1:]` and checks mode and size only for those.\n\nFor an `I` or `F` image the 8-bit plane `image8` is NULL (only `image32` is set). `ImagingMerge` dereferences `bands[0]->image8[y]` for the multi-band output modes:\n\n- `src/libImaging/Bands.c:302`, `:311`, `:321`\n\nThe IPTC loader builds the band list from an attacker-typed sub-image and passes it to merge with the sub-image at index 0:\n\n- `src/PIL/IptcImagePlugin.py:156-160`\n- `src/PIL/IptcImagePlugin.py:169` registers the opener with no accept function.\n\n### PoC\n```python\nfrom PIL import Image\n\n# Band 0 is a single-band \"I\" image: its image8 plane is NULL. merge() validates only\n# bands[1:], so the native ImagingMerge dereferences the NULL plane for band 0.\nband0 = Image.new(\"I\", (4, 4))\nImage.merge(\"RGB\", [band0, Image.new(\"L\", (4, 4)), Image.new(\"L\", (4, 4))])\n```\n\nRun it:\n```\n$ python 02_poc.py\nSegmentation fault (core dumped)\n```\n\nObserved on a source build of commit `3e2ab96`.\n\nUnder AddressSanitizer:\n```\n==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000\n    #0 ImagingMerge   src/libImaging/Bands.c:311\n    #1 _merge         src/_imaging.c:2492\nSUMMARY: AddressSanitizer: SEGV src/libImaging/Bands.c:311 in ImagingMerge\n```\nThe null address confirms the dereference of the missing `image8` plane for band 0.\n\n### Impact\nNULL pointer dereference in a C extension. A crafted file opened and loaded through the IPTC path crashes the worker process. This is a hard crash, not a Python exception an application can catch.","categories":["Libraries & packages"],"product":"pillow","vendor":"python-pillow","ecosystem":"pip","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-cp9v-662q-vvx9","source_modified_at":"2026-10-21T20:30:26Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"pip","name":"pillow"},"range":">= 12.0.0, < 13.0.0"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-112405","source_modified_at":"2026-10-20T15:56:29.299Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"Pillow","vendor":"python-pillow","versions":[{"version":">= 12.0.0, < 13.0.0","status":"affected"}],"defaultStatus":null},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-cp9v-662q-vvx9","source_modified_at":"2026-10-21T20:45:04.636143652Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"PyPI","name":"pillow","purl":"pkg:pypi/pillow"},"ranges":[{"events":[{"introduced":"12.0.0"},{"fixed":"13.0.0"}],"type":"ECOSYSTEM"}],"versions":["12.0.0","12.1.0","12.1.1","12.2.0","12.3.0"]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-cp9v-662q-vvx9","source_modified_at":"2026-10-21T20:30:26Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"pip","name":"pillow"},"version":"13.0.0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-cp9v-662q-vvx9","source_modified_at":"2026-10-21T20:45:04.636143652Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"PyPI","name":"pillow","purl":"pkg:pypi/pillow"},"version":"13.0.0"}],"cvss":8.7,"severity":"High","kev":{"listed":false},"epss":{"probability":0.00291,"percentile":0.20607,"score_date":"2026-10-23"},"published_at":"2026-10-19T21:29:53.515Z","modified_at":"2026-10-21T20:45:04.636143652Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-cp9v-662q-vvx9","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-21T20:30:26Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-112405","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-20T15:56:29.299Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-cp9v-662q-vvx9","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-21T20:45:04.636143652Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-112405","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/python-pillow/Pillow/security/advisories/GHSA-cp9v-662q-vvx9","tags":["x_refsource_CONFIRM"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-112405","source":"GitHub Advisory Database"},{"source":"CVE List","url":"https://github.com/python-pillow/Pillow/commit/b6ee66e8b2c2c0932bdf65f963268d9f2927ef86","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/python-pillow/Pillow/releases/tag/13.0.0","tags":["x_refsource_MISC"]},{"url":"https://github.com/advisories/GHSA-cp9v-662q-vvx9","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"poc","automatable":"yes","technical_impact":"partial","assessed_at":"2026-10-20T15:56:00.942567Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"product","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-21T20:45:04.636143652Z","content_hash":"630b4a77c3ad08d199a7b686033146f0975b458e22ccfb9e2d78995f2e4fad32"}}
