{"id":"CVE-2026-96641","aliases":["BIT-pillow-2026-96641","CLSA-2026-1793017750","CLSA-2026-1793085879","CLSA-2026-1793099358","CLSA-2026-1793346161","DEBIAN-CVE-2026-96641","EUVD-2026-107562","GHSA-4rm8-3hmm-39fg","PYSEC-2026-4340","SUSE-SU-2026:5038-1","UBUNTU-CVE-2026-96641"],"status":"published","title":"Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","severity":{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00345,"percentile":0.28205,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-190"],"published":"2026-10-21T20:51:24Z","modified":"2026-11-04T20:04:29Z","fixes":[{"ecosystem":"PyPI","package":"pillow","fixed_in":["13.0.0"],"sources":["ghsa","osv"]},{"ecosystem":"Bitnami","package":"pillow","fixed_in":["13.0.0"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"13.0.0"}]}]},{"source":"osv","ecosystem":"Bitnami","package":"pillow","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"13.0.0"}]}]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"11.3.0"},{"fixed":"11.3.0.post11+tuxcare"}]}],"versions":["11.3.0","11.3.0.post1+tuxcare","11.3.0.post10+tuxcare","11.3.0.post2+tuxcare","11.3.0.post3+tuxcare","11.3.0.post4+tuxcare","11.3.0.post5+tuxcare","11.3.0.post6+tuxcare","11.3.0.post7+tuxcare","11.3.0.post8+tuxcare","11.3.0.post9+tuxcare"],"bundled":9},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"11.2.1"},{"fixed":"11.2.1.post13+tuxcare"}]}],"versions":["11.2.1","11.2.1.post1+tuxcare","11.2.1.post10+tuxcare","11.2.1.post11+tuxcare","11.2.1.post12+tuxcare","11.2.1.post2+tuxcare","11.2.1.post3+tuxcare","11.2.1.post4+tuxcare","11.2.1.post5+tuxcare","11.2.1.post6+tuxcare","11.2.1.post7+tuxcare","11.2.1.post8+tuxcare","11.2.1.post9+tuxcare"],"bundled":9},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"10.4.0"},{"fixed":"10.4.0.post15+tuxcare"}]}],"versions":["10.4.0","10.4.0.post1+tuxcare","10.4.0.post10+tuxcare","10.4.0.post11+tuxcare","10.4.0.post12+tuxcare","10.4.0.post13+tuxcare","10.4.0.post14+tuxcare","10.4.0.post2+tuxcare","10.4.0.post3+tuxcare","10.4.0.post4+tuxcare","10.4.0.post5+tuxcare","10.4.0.post6+tuxcare","10.4.0.post7+tuxcare","10.4.0.post8+tuxcare","10.4.0.post9+tuxcare"],"bundled":8},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"9.5.0"},{"fixed":"9.5.0.post13+tuxcare"}]}],"versions":["9.5.0","9.5.0.post1+tuxcare","9.5.0.post10+tuxcare","9.5.0.post11+tuxcare","9.5.0.post12+tuxcare","9.5.0.post2+tuxcare","9.5.0.post3+tuxcare","9.5.0.post4+tuxcare","9.5.0.post5+tuxcare","9.5.0.post6+tuxcare","9.5.0.post7+tuxcare","9.5.0.post8+tuxcare","9.5.0.post9+tuxcare"],"bundled":7},{"source":"osv","ecosystem":"Debian:12","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["10.0.0-1","10.1.0-1","10.2.0-1","10.3.0-1","10.3.0-2","10.4.0-1","10.4.0-1.1","11.1.0-1","11.1.0-2","11.1.0-3","11.1.0-4","11.1.0-5","11.2.1-1","11.3.0-1","12.0.0-1","12.1.0-1","12.1.1-1","12.1.1-2","12.2.0-1","12.3.0-1","13.0.0-1","9.4.0-1.1","9.4.0-1.1+deb12u1","9.5.0-1"]},{"source":"osv","ecosystem":"Debian:13","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["11.1.0-5","11.1.0-5+deb13u1","11.1.0-5+deb13u2","11.1.0-5+deb13u3","11.1.0-5+deb13u4","11.2.1-1","11.3.0-1","12.0.0-1","12.1.0-1","12.1.1-1","12.1.1-2","12.2.0-1","12.3.0-1","13.0.0-1"]},{"source":"osv","ecosystem":"Debian:14","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["11.1.0-5","11.2.1-1","11.3.0-1","12.0.0-1","12.1.0-1","12.1.1-1","12.1.1-2","12.2.0-1","12.3.0-1","13.0.0-1"]},{"source":"osv","ecosystem":"PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"13.0.0"}]}],"versions":["1.0","1.1","1.2","1.3","1.4","1.5","1.6","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","10.0.0","10.0.1","10.1.0","10.2.0","10.3.0","10.4.0","11.0.0","11.1.0","11.2.1","11.3.0","12.0.0","12.1.0","12.1.1","12.2.0","12.3.0","2.0.0","2.1.0","2.2.0","2.2.1","2.2.2","2.3.0","2.3.1","2.3.2","2.4.0","2.5.0","2.5.1","2.5.2","2.5.3","2.6.0","2.6.1","2.6.2","2.7.0","2.8.0","2.8.1","2.8.2","2.9.0","3.0.0","3.1.0","3.1.0.rc1","3.1.0rc1","3.1.1","3.1.2","3.2.0","3.3.0","3.3.1","3.3.2","3.3.3","3.4.0","3.4.1","3.4.2","4.0.0","4.1.0","4.1.1","4.2.0","4.2.1","4.3.0","5.0.0","5.1.0","5.2.0","5.3.0","5.4.0","5.4.0.dev0","5.4.1","6.0.0","6.1.0","6.2.0","6.2.1","6.2.2","7.0.0","7.1.0","7.1.1","7.1.2","7.2.0","8.0.0","8.0.1","8.1.0","8.1.1","8.1.2","8.2.0","8.3.0","8.3.1","8.3.2","8.4.0","9.0.0","9.0.1","9.1.0","9.1.1","9.2.0","9.3.0","9.4.0","9.5.0"]},{"source":"osv","ecosystem":"PyPI","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"13.0.0"}]}],"versions":["1.0","1.1","1.2","1.3","1.4","1.5","1.6","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.7.7","1.7.8","10.0.0","10.0.1","10.1.0","10.2.0","10.3.0","10.4.0","11.0.0","11.1.0","11.2.1","11.3.0","12.0.0","12.1.0","12.1.1","12.2.0","12.3.0","2.0.0","2.1.0","2.2.0","2.2.1","2.2.2","2.3.0","2.3.1","2.3.2","2.4.0","2.5.0","2.5.1","2.5.2","2.5.3","2.6.0","2.6.1","2.6.2","2.7.0","2.8.0","2.8.1","2.8.2","2.9.0","3.0.0","3.1.0","3.1.0.rc1","3.1.0rc1","3.1.1","3.1.2","3.2.0","3.3.0","3.3.1","3.3.2","3.3.3","3.4.0","3.4.1","3.4.2","4.0.0","4.1.0","4.1.1","4.2.0","4.2.1","4.3.0","5.0.0","5.1.0","5.2.0","5.3.0","5.4.0","5.4.0.dev0","5.4.1","6.0.0","6.1.0","6.2.0","6.2.1","6.2.2","7.0.0","7.1.0","7.1.1","7.1.2","7.2.0","8.0.0","8.0.1","8.1.0","8.1.1","8.1.2","8.2.0","8.3.0","8.3.1","8.3.2","8.4.0","9.0.0","9.0.1","9.1.0","9.1.1","9.2.0","9.3.0","9.4.0","9.5.0"]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Module for Package Hub 15 SP7","package":"python-Pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"7.2.0-150300.3.33.1"}]}],"bundled":29},{"source":"osv","ecosystem":"Ubuntu:Pro:14.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.2.1-1ubuntu2","2.2.1-2ubuntu1","2.2.1-3ubuntu2","2.2.1-3ubuntu3","2.2.1-3ubuntu4","2.2.1-3ubuntu6","2.3.0-1ubuntu1","2.3.0-1ubuntu2","2.3.0-1ubuntu3","2.3.0-1ubuntu3.2","2.3.0-1ubuntu3.3","2.3.0-1ubuntu3.4","2.3.0-1ubuntu3.4+esm1","2.3.0-1ubuntu3.4+esm2","2.3.0-1ubuntu3.4+esm3","2.3.0-1ubuntu3.4+esm4","2.3.0-1ubuntu3.4+esm5"]},{"source":"osv","ecosystem":"Ubuntu:Pro:16.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.9.0-1","3.0.0-1","3.0.0-1build1","3.1.0-1","3.1.1-1","3.1.2-0ubuntu1","3.1.2-0ubuntu1.1","3.1.2-0ubuntu1.3","3.1.2-0ubuntu1.4","3.1.2-0ubuntu1.5","3.1.2-0ubuntu1.6","3.1.2-0ubuntu1.6+esm1","3.1.2-0ubuntu1.6+esm2","3.1.2-0ubuntu1.6+esm3"]},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["4.1.1-3build2","4.3.0-2ubuntu1","5.0.0-1","5.1.0-1","5.1.0-1ubuntu0.2","5.1.0-1ubuntu0.3","5.1.0-1ubuntu0.4","5.1.0-1ubuntu0.5","5.1.0-1ubuntu0.6","5.1.0-1ubuntu0.7","5.1.0-1ubuntu0.8","5.1.0-1ubuntu0.8+esm1","5.1.0-1ubuntu0.8+esm2"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["6.1.0-1","6.1.0-1build1","6.2.1-2","7.0.0-4","7.0.0-4build1","7.0.0-4ubuntu0.1","7.0.0-4ubuntu0.2","7.0.0-4ubuntu0.3","7.0.0-4ubuntu0.4","7.0.0-4ubuntu0.5","7.0.0-4ubuntu0.6","7.0.0-4ubuntu0.7","7.0.0-4ubuntu0.8","7.0.0-4ubuntu0.9","7.0.0-4ubuntu0.9+esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"pillow-python2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["6.2.1-3~build1","6.2.1-3","6.2.1-3ubuntu0.1~esm1","6.2.1-3ubuntu0.1~esm2"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["8.1.2+dfsg-0.3","9.0.0-1","9.0.1-1","9.0.1-1build1","9.0.1-1ubuntu0.1","9.0.1-1ubuntu0.2","9.0.1-1ubuntu0.3","9.0.1-1ubuntu0.4","9.0.1-1ubuntu0.5","9.0.1-1ubuntu0.6"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["10.0.0-1","10.1.0-1","10.2.0-1","10.2.0-1build1","10.2.0-1ubuntu1","10.2.0-1ubuntu1.2","10.2.0-1ubuntu1.3","10.2.0-1ubuntu1.4"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["12.1.1-2ubuntu1","12.3.0-1ubuntu1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"pillow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["11.3.0-1ubuntu1","11.3.0-1ubuntu2","12.0.0-1ubuntu1","12.1.1-1ubuntu1","12.1.1-2ubuntu1","12.1.1-2ubuntu1.1","12.1.1-2ubuntu1.2","12.1.1-2ubuntu1.3","12.1.1-2ubuntu1.4"]}],"products":[{"vendor":"python","product":"pillow"},{"vendor":"python-pillow","product":"pillow"}],"references":[{"url":"https://github.com/python-pillow/Pillow/security/advisories/GHSA-4rm8-3hmm-39fg","tags":["x_refsource_CONFIRM","Vendor Advisory","advisory","web","report"]},{"url":"https://github.com/python-pillow/Pillow/pull/10010","tags":["x_refsource_MISC","Issue Tracking","report","fix","web"]},{"url":"https://github.com/python-pillow/Pillow/commit/80de4be9e38d3a6148dd4d8491eb80cd12b760a4","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/python-pillow/Pillow/releases/tag/13.0.0","tags":["x_refsource_MISC","Release Notes","article","web","advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-96641","tags":["web","advisory"]},{"url":"https://github.com/advisories/GHSA-4rm8-3hmm-39fg"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/96xxx/CVE-2026-96641.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-96641","tags":["advisory"]},{"url":"https://github.com/python-pillow/Pillow","tags":["package"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-20265038-1/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1286256","tags":["report"]},{"url":"https://bugzilla.suse.com/1286273","tags":["report"]},{"url":"https://bugzilla.suse.com/1286287","tags":["report"]},{"url":"https://bugzilla.suse.com/1286311","tags":["report"]},{"url":"https://bugzilla.suse.com/1286314","tags":["report"]},{"url":"https://bugzilla.suse.com/1286325","tags":["report"]},{"url":"https://bugzilla.suse.com/1286368","tags":["report"]},{"url":"https://bugzilla.suse.com/1286370","tags":["report"]},{"url":"https://bugzilla.suse.com/1286372","tags":["report"]},{"url":"https://bugzilla.suse.com/1286381","tags":["report"]},{"url":"https://bugzilla.suse.com/1286396","tags":["report"]},{"url":"https://bugzilla.suse.com/1286397","tags":["report"]},{"url":"https://bugzilla.suse.com/1286398","tags":["report"]},{"url":"https://bugzilla.suse.com/1286400","tags":["report"]},{"url":"https://bugzilla.suse.com/1286401","tags":["report"]},{"url":"https://bugzilla.suse.com/1286402","tags":["report"]},{"url":"https://bugzilla.suse.com/1286403","tags":["report"]},{"url":"https://bugzilla.suse.com/1286404","tags":["report"]},{"url":"https://bugzilla.suse.com/1286405","tags":["report"]},{"url":"https://bugzilla.suse.com/1286406","tags":["report"]},{"url":"https://bugzilla.suse.com/1286408","tags":["report"]},{"url":"https://bugzilla.suse.com/1286411","tags":["report"]},{"url":"https://bugzilla.suse.com/1286489","tags":["report"]},{"url":"https://bugzilla.suse.com/1286796","tags":["report"]},{"url":"https://bugzilla.suse.com/1286797","tags":["report"]},{"url":"https://bugzilla.suse.com/1286798","tags":["report"]},{"url":"https://bugzilla.suse.com/1286801","tags":["report"]},{"url":"https://bugzilla.suse.com/1286802","tags":["report"]},{"url":"https://bugzilla.suse.com/1286804","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112390","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112391","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112392","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112393","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112394","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112397","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112398","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112399","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112400","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112401","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112402","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112403","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112405","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112406","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112891","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112892","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112894","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112895","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112896","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112897","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112899","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112900","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112901","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-112902","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-96636","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-96637","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-96640","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-96641","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-96642","tags":["web"]},{"url":"https://ubuntu.com/security/CVE-2026-96641","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-96641","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-96641","title":"Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T20:51:24.388Z","modified":"2026-10-28T01:50:42.16Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium","assessor":"cna"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T14:20:00.511569Z"}],"euvd":[{"id":"EUVD-2026-107562","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T20:51:24Z","modified":"2026-10-28T01:50:42Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"updated_at":"2026-11-02T16:59:22.052945Z"}],"ghsa":[{"id":"GHSA-4rm8-3hmm-39fg","title":"Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise","description":"### Summary\nAffected Object and Source\n\nPackage: Pillow 12.3.0\nSource: PyPI sdist pillow-12.3.0.tar.gz\nSHA-256: 3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce\nSink: src/_imaging.c:2809:15, xsize += dx\n\n### Details\nThe code in Pillow 12.3.0 is:\n```c\nfor (xsize = 0; *text; text++) {\n    int dx = self-\u003eglyphs[*text].dx;\n    if (dx \u003e 0 \u0026\u0026 xsize \u003e INT_MAX - dx) {\n        PyErr_SetString(PyExc_OverflowError, \"Width too large\");\n        return -1;\n    }\n    xsize += dx;\n}\n```\nThe PILfont glyph advance is parsed from a signed 16-bit field, so the valid range for `dx` is `[-32768, 32767]`. The existing check only proves:\n`dx \u003e 0 =\u003e xsize \u003c= INT_MAX - dx`\nIt does **not** prove the other half of the contract:\n`dx \u003c 0 =\u003e xsize \u003e= INT_MIN - dx`\nTaking `dx = -32768` and repeating it 65,537 times, the mathematical sum is `-2,147,516,416`, which is less than `INT_MIN = -2,147,483,648`. On the 65,537th addition, the operation `-2147483648 + -32768` is performed, resulting in **C signed overflow undefined behavior**.\n\n### PoC\n```python\n\"\"\"Minimal public-API reproducer for the Pillow 12.3.0 textwidth underflow.\n\nRun with an ordinary Pillow 12.3.0 build to observe the wrapped width, or with\nthe PyC-Contract UBSan build to obtain the exact native diagnostic.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport struct\nfrom io import BytesIO\n\nimport PIL\nfrom PIL import Image, ImageFont\n\n\nADVANCE = -(2**15)\nCONTROL_REPEAT = 65_536\nWITNESS_REPEAT = 65_537\n\n\ndef bitmap_font(advance: int) -\u003e ImageFont.ImageFont:\n    metrics = bytearray(256 * 20)\n    glyph_offset = ord(\"A\") * 20\n    metrics[glyph_offset : glyph_offset + 2] = struct.pack(\"\u003eh\", advance)\n    font_data = b\"PILfont\\n;;;;;;1;\\nDATA\\n\" + bytes(metrics)\n    font = ImageFont.ImageFont()\n    font._load_pilfont_data(BytesIO(font_data), Image.new(\"1\", (1, 1)))\n    return font\n\n\ndef main() -\u003e None:\n    font = bitmap_font(ADVANCE)\n    print(f\"Pillow={PIL.__version__}\")\n    print(f\"control_math={ADVANCE * CONTROL_REPEAT}\")\n    print(f\"control_return={font.getlength('A' * CONTROL_REPEAT)}\")\n    print(f\"witness_math={ADVANCE * WITNESS_REPEAT}\")\n    print(f\"witness_return={font.getlength('A' * WITNESS_REPEAT)}\")\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\nObservations from a regular 12.3.0 release build:\n\n```text\nPillow=12.3.0\ncontrol_math=-2147483648\ncontrol_return=0\nwitness_math=-2147516416\nwitness_return=2147450880\n```\n\nThe adjacent control uses 65,536 repetitions, producing a mathematical result of exactly `INT_MIN`, and the function subsequently returns 0 according to existing semantics. Adding just a single character flips the return value to `2,147,450,880`.\n\n\n### Impact\nThe directly confirmed impact is width semantic integrity violation: getlength() and boundary calculations based on getsize() may return a huge positive value, while the true mathematical width is negative. The high-level getmask() typically passes through the decompression-bomb check, which mitigates the risk of direct massive allocation; however, internal font objects and applications that use the width for layout, quotas, serialization, or subsequent allocations may be affected by resource consumption or logic errors.\n\nTherefore, the current recommended severity rating is \"Reachable native integer undefined behavior, with potential DoS/logic integrity impact; specific security severity to be confirmed by the upstream threat model\", rather than a memory corruption vulnerability.\n\n### Recommended Patch and Regression Tests\n\nIt is recommended to extend the overflow check to cover both directions:\n```c\nif ((dx \u003e 0 \u0026\u0026 xsize \u003e INT_MAX - dx) ||\n    (dx \u003c 0 \u0026\u0026 xsize \u003c INT_MIN - dx)) {\n    PyErr_SetString(PyExc_OverflowError, \"Width too large\");\n    return -1;\n}\n```\nAt a minimum, four test cases should be added:\n1. `dx = 32767, repeat = 65538` — upper adjacent control (should succeed);\n2. `dx = 32767, repeat = 65539` — should raise `OverflowError`;\n3. `dx = -32768, repeat = 65536` — lower adjacent control (should succeed);\n4. `dx = -32768, repeat = 65537` — should raise `OverflowError`.\n\nAdditionally, it should be verified that exception propagation is consistent across `getlength()`, `getbbox()`, `getmask()`, and the underlying `font.getsize()`.","status":"published","published":"2026-10-22T16:01:14Z","modified":"2026-10-22T16:01:15Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T14:41:34.690842Z"}],"nvd":[{"id":"CVE-2026-96641","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T21:20:32.5Z","modified":"2026-10-28T02:17:08.123Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium","assessor":"secondary"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T14:13:02.371082Z"}],"osv":[{"id":"CVE-2026-96641","title":"Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T20:51:24.388Z","modified":"2026-11-03T13:27:01.278378293Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"cwes":["CWE-190"],"updated_at":"2026-11-03T14:04:55.31869Z"},{"id":"DEBIAN-CVE-2026-96641","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T21:20:32.5Z","modified":"2026-10-28T09:47:39.177825324Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"updated_at":"2026-11-02T15:46:07.324252Z"},{"id":"GHSA-4rm8-3hmm-39fg","title":"Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise","description":"### Summary\nAffected Object and Source\n\nPackage: Pillow 12.3.0\nSource: PyPI sdist pillow-12.3.0.tar.gz\nSHA-256: 3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce\nSink: src/_imaging.c:2809:15, xsize += dx\n\n### Details\nThe code in Pillow 12.3.0 is:\n```c\nfor (xsize = 0; *text; text++) {\n    int dx = self-\u003eglyphs[*text].dx;\n    if (dx \u003e 0 \u0026\u0026 xsize \u003e INT_MAX - dx) {\n        PyErr_SetString(PyExc_OverflowError, \"Width too large\");\n        return -1;\n    }\n    xsize += dx;\n}\n```\nThe PILfont glyph advance is parsed from a signed 16-bit field, so the valid range for `dx` is `[-32768, 32767]`. The existing check only proves:\n`dx \u003e 0 =\u003e xsize \u003c= INT_MAX - dx`\nIt does **not** prove the other half of the contract:\n`dx \u003c 0 =\u003e xsize \u003e= INT_MIN - dx`\nTaking `dx = -32768` and repeating it 65,537 times, the mathematical sum is `-2,147,516,416`, which is less than `INT_MIN = -2,147,483,648`. On the 65,537th addition, the operation `-2147483648 + -32768` is performed, resulting in **C signed overflow undefined behavior**.\n\n### PoC\n```python\n\"\"\"Minimal public-API reproducer for the Pillow 12.3.0 textwidth underflow.\n\nRun with an ordinary Pillow 12.3.0 build to observe the wrapped width, or with\nthe PyC-Contract UBSan build to obtain the exact native diagnostic.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport struct\nfrom io import BytesIO\n\nimport PIL\nfrom PIL import Image, ImageFont\n\n\nADVANCE = -(2**15)\nCONTROL_REPEAT = 65_536\nWITNESS_REPEAT = 65_537\n\n\ndef bitmap_font(advance: int) -\u003e ImageFont.ImageFont:\n    metrics = bytearray(256 * 20)\n    glyph_offset = ord(\"A\") * 20\n    metrics[glyph_offset : glyph_offset + 2] = struct.pack(\"\u003eh\", advance)\n    font_data = b\"PILfont\\n;;;;;;1;\\nDATA\\n\" + bytes(metrics)\n    font = ImageFont.ImageFont()\n    font._load_pilfont_data(BytesIO(font_data), Image.new(\"1\", (1, 1)))\n    return font\n\n\ndef main() -\u003e None:\n    font = bitmap_font(ADVANCE)\n    print(f\"Pillow={PIL.__version__}\")\n    print(f\"control_math={ADVANCE * CONTROL_REPEAT}\")\n    print(f\"control_return={font.getlength('A' * CONTROL_REPEAT)}\")\n    print(f\"witness_math={ADVANCE * WITNESS_REPEAT}\")\n    print(f\"witness_return={font.getlength('A' * WITNESS_REPEAT)}\")\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\nObservations from a regular 12.3.0 release build:\n\n```text\nPillow=12.3.0\ncontrol_math=-2147483648\ncontrol_return=0\nwitness_math=-2147516416\nwitness_return=2147450880\n```\n\nThe adjacent control uses 65,536 repetitions, producing a mathematical result of exactly `INT_MIN`, and the function subsequently returns 0 according to existing semantics. Adding just a single character flips the return value to `2,147,450,880`.\n\n\n### Impact\nThe directly confirmed impact is width semantic integrity violation: getlength() and boundary calculations based on getsize() may return a huge positive value, while the true mathematical width is negative. The high-level getmask() typically passes through the decompression-bomb check, which mitigates the risk of direct massive allocation; however, internal font objects and applications that use the width for layout, quotas, serialization, or subsequent allocations may be affected by resource consumption or logic errors.\n\nTherefore, the current recommended severity rating is \"Reachable native integer undefined behavior, with potential DoS/logic integrity impact; specific security severity to be confirmed by the upstream threat model\", rather than a memory corruption vulnerability.\n\n### Recommended Patch and Regression Tests\n\nIt is recommended to extend the overflow check to cover both directions:\n```c\nif ((dx \u003e 0 \u0026\u0026 xsize \u003e INT_MAX - dx) ||\n    (dx \u003c 0 \u0026\u0026 xsize \u003c INT_MIN - dx)) {\n    PyErr_SetString(PyExc_OverflowError, \"Width too large\");\n    return -1;\n}\n```\nAt a minimum, four test cases should be added:\n1. `dx = 32767, repeat = 65538` — upper adjacent control (should succeed);\n2. `dx = 32767, repeat = 65539` — should raise `OverflowError`;\n3. `dx = -32768, repeat = 65536` — lower adjacent control (should succeed);\n4. `dx = -32768, repeat = 65537` — should raise `OverflowError`.\n\nAdditionally, it should be verified that exception propagation is consistent across `getlength()`, `getbbox()`, `getmask()`, and the underlying `font.getsize()`.","status":"published","published":"2026-10-22T16:01:14Z","modified":"2026-10-29T10:56:07.449486409Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"cwes":["CWE-190"],"updated_at":"2026-11-02T15:46:37.528068Z"},{"id":"PYSEC-2026-4340","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T21:20:32.5Z","modified":"2026-10-29T10:56:07.449486409Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"updated_at":"2026-11-02T15:52:57.671918Z"},{"id":"UBUNTU-CVE-2026-96641","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-21T21:20:00Z","modified":"2026-11-04T20:04:29.237193247Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H","level":"medium"}],"updated_at":"2026-11-04T21:43:26.87909Z"},{"id":"BIT-pillow-2026-96641","title":"Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise","description":"Pillow is a Python imaging library. Prior to 13.0.0, PILfont text-width accumulation in src/_imaging.c checks positive glyph advances against INT_MAX but does not check negative advances against INT_MIN. Repeating a signed 16-bit advance of -32768 can therefore execute a signed C integer overflow in xsize += dx, producing a large positive width from a negative mathematical result. Applications that use getlength(), getsize(), or derived layout, quota, serialization, or allocation calculations can experience logic-integrity errors or resource consumption, while the high-level mask path commonly retains a decompression-bomb check. This issue is fixed in version 13.0.0.","status":"published","published":"2026-10-29T08:58:16.836Z","modified":"2026-10-29T10:56:07.449486409Z","updated_at":"2026-11-02T15:28:34.724063Z"},{"id":"CLSA-2026-1793017750","title":"TuxCare security update for pillow (9 CVEs)","description":"TuxCare rebuilt pillow to address 9 CVEs. Fixed in 11.3.0.post11+tuxcare.","status":"published","published":"2026-10-26T12:29:10Z","modified":"2026-10-27T01:45:02.436944916Z","updated_at":"2026-11-02T15:43:54.981307Z"},{"id":"CLSA-2026-1793085879","title":"TuxCare security update for pillow (9 CVEs)","description":"TuxCare rebuilt pillow to address 9 CVEs. Fixed in 11.2.1.post13+tuxcare.","status":"published","published":"2026-10-27T07:24:39Z","modified":"2026-10-27T13:30:19.34042906Z","updated_at":"2026-11-02T15:43:54.981307Z"},{"id":"CLSA-2026-1793099358","title":"TuxCare security update for pillow (8 CVEs)","description":"TuxCare rebuilt pillow to address 8 CVEs. Fixed in 10.4.0.post15+tuxcare.","status":"published","published":"2026-10-27T11:09:18Z","modified":"2026-10-27T13:30:19.345594865Z","updated_at":"2026-11-02T15:43:55.34846Z"},{"id":"CLSA-2026-1793346161","title":"TuxCare security update for pillow (7 CVEs)","description":"TuxCare rebuilt pillow to address 7 CVEs. Fixed in 9.5.0.post13+tuxcare.","status":"published","published":"2026-10-30T08:42:41Z","modified":"2026-10-30T13:30:11.642926727Z","updated_at":"2026-11-02T15:43:55.669514Z"},{"id":"SUSE-SU-2026:5038-1","title":"Security update for python-Pillow","description":"This update for python-Pillow fixes the following issues:\n\n- CVE-2026-96636: decompression-bomb protection bypass via multi-frame `seek()` in MPO and DCX (bsc#1286802).\n- CVE-2026-96637: decompression bomb check bypass in `SpiderImagePlugin.seek()` leads to unbounded allocation DoS\n  (bsc#1286801).\n- CVE-2026-96640: PDF append accepts malformed shared page-tree DAG, which can cause resource exhaustion (bsc#1286798).\n- CVE-2026-96641: reachable undefined behavior in native integer operations can lead to denial of service or logic\n  integrity compromise (bsc#1286797).\n- CVE-2026-96642: `TarIO` negative size field causes infinite CPU-spin loop (bsc#1286796).\n- CVE-2026-112390: Denial of Service via infinite loop during crafted MIC image parsing (bsc#1286256).\n- CVE-2026-112391: Denial of Service via unbounded recursion in PDF parser (bsc#1286273).\n- CVE-2026-112392: Denial of Service via zero-size images in rank filters (bsc#1286287).\n- CVE-2026-112393: heap buffer overflow and stale-heap disclosure in _tiffWriteProc when saving compressed TIFF data\n  (bsc#1286325).\n- CVE-2026-112394: `P;2L` and `P;4L` decoders may read 1 to 3 bytes past the passed buffer size (bsc#1286311).\n- CVE-2026-112397: out-of-bounds access in `_imagingmorph` on a zero-width image (bsc#1286314).\n- CVE-2026-112398: heap buffer overflow in FPX JPEG decoding can lead to code execution (bsc#1286406).\n- CVE-2026-112399: Denial of service via crafted APNG image (bsc#1286368).\n- CVE-2026-112400: Denial of Service via memory exhaustion from crafted GIF image (bsc#1286370).\n- CVE-2026-112401: Denial of Service via crafted GIF comments (bsc#1286372).\n- CVE-2026-112402: Denial of service via double free during image transformation (bsc#1286381).\n- CVE-2026-112403: heap buffer overflow in `ImagingJpegDecode` allows for code execution (bsc#1286405).\n- CVE-2026-112405: NULL pointer dereference in `Image.merge` via an unvalidated band 0 (bsc#1286404).\n- CVE-2026-112406: infinite loop in `PdfParser.rewrite_pages` on page tree `Parent` cycle (bsc#1286403).\n- CVE-2026-112891: quadratic GIF comment copying during save (bsc#1286402).\n- CVE-2026-112892: MSP RLE decoder expands a tiny file into unbounded memory (bsc#1286401).\n- CVE-2026-112894: Denial of Service via crafted multi-frame image conversion (bsc#1286408).\n- CVE-2026-112895: Denial of service via crafted PDF during append operations (bsc#1286411).\n- CVE-2026-112896: TIFF encoder `ColorMap` plane-size mismatch causes a heap out-of-bounds read (bsc#1286400).\n- CVE-2026-112897: `TiffDecode` returns uninitialized memory as pixels for short JPEG strips (bsc#1286398).\n- CVE-2026-112899: EPS `load(scale)` lets Ghostscript render past the decompression bomb limit (bsc#1286489).\n- CVE-2026-112900: argument Injection in Ghostscript call can lead to remote code execution (bsc#1286397).\n- CVE-2026-112901: ReDoS in `XbmImagePlugin` can be triggered by 512-byte file (bsc#1286396).\n- CVE-2026-112902: memory disclosure and segfault in libtiff encoder via crafted TIFF tags (bsc#1286804).\n","status":"published","published":"2026-11-02T16:22:03Z","modified":"2026-11-03T13:15:08.326276184Z","updated_at":"2026-11-03T13:33:04.521148Z"}]}}
