CVE-2026-34789 Overview
CVE-2026-34789 is a code injection vulnerability in FreeCAD, an open-source multiplatform 3D parametric modeler. Versions prior to 1.1.2 mishandle deserialization of PropertyPythonObject data inside FCStd documents. The PropertyPythonObject::Restore() function in src/App/PropertyPythonObject.cpp passes an attacker-controlled module attribute directly to PyImport_ImportModule(). A legacy pickle branch additionally imports an attacker-controlled module and invokes its class constructor via PyObject_CallObject(). Opening a crafted FCStd file executes module-level Python code in the user's context. The issue is fixed in FreeCAD 1.1.2 and tracked as CWE-94: Improper Control of Generation of Code.
Critical Impact
A user who opens a malicious FCStd document triggers arbitrary Python execution with the privileges of the FreeCAD process, resulting in full confidentiality, integrity, and availability compromise on the local host.
Affected Products
- FreeCAD versions prior to 1.1.2
- src/App/PropertyPythonObject.cpp component (Restore path)
- Legacy pickle deserialization branch in PropertyPythonObject
Discovery Timeline
- 2026-08-17 - CVE-2026-34789 published to NVD
- 2026-08-19 - Last updated in NVD database
- Fix released - FreeCAD Release Version 1.1.2
- Advisory published - FreeCAD Security Advisory GHSA-493w-pp4h-h77v
Technical Details for CVE-2026-34789
Vulnerability Analysis
FreeCAD serializes Python-backed properties into FCStd documents using an XML representation of PropertyPythonObject. During load, PropertyPythonObject::Restore() reads the serialized module attribute and passes the string directly to CPython's PyImport_ImportModule(). Importing a Python module executes its top-level code, so any attacker who can influence the module field controls what runs. A secondary legacy pickle branch compounds the exposure. It imports an attacker-supplied module and then calls its class constructor through PyObject_CallObject(), providing a second reliable code execution primitive. Both paths are reached simply by opening a crafted document, which is a common workflow for FreeCAD users who share .FCStd files. The flaw is classified as CWE-94, improper control of code generation.
Root Cause
The restore routine treats serialized document metadata as trusted input. It performs no allowlist check, no path validation, and no signature verification before invoking Python's import machinery. Any string in the XML module field is imported, and any class name is instantiated.
Attack Vector
Exploitation requires local user interaction. An attacker crafts a .FCStd file containing a malicious PropertyPythonObject and delivers it via email, chat, model repositories, or shared project folders. When a victim opens the file in a vulnerable FreeCAD build, Python code executes without further prompts.
// Patch excerpt: src/App/PropertyPythonObject.cpp
// Use FreeCAD.__ModDirs__ as the authoritative list of allowed module directories.
// This is populated during startup by FreeCADInit.py and includes built-in workbenches,
// user addons, and any additional configured module paths.
Py::Module freecad(PyImport_ImportModule("FreeCAD"), true);
if (!freecad.hasAttr("__ModDirs__")) {
throw Py::RuntimeError("FreeCAD.__ModDirs__ not set -- FreeCADInit.py has not run yet");
}
Py::List modDirs(freecad.getAttr("__ModDirs__"));
auto isUnderFreeCAD = [&](const std::string& path) {
for (int i = 0; i < static_cast<int>(modDirs.size()); ++i) {
if (isUnderDirectory(path, Py::String(modDirs[i]).as_std_string())) {
return true;
}
}
return false;
};
// Source: https://github.com/FreeCAD/FreeCAD/commit/e2dc6c8172673642c6856b8b3a5a6accefb18279
The patch restricts imports to modules whose origin resides under directories listed in FreeCAD.__ModDirs__, blocking arbitrary module paths supplied via crafted documents. A companion change removes the exposed loadPickle() helper from the public header (commit 81b7392, commit 983037f).
Detection Methods for CVE-2026-34789
Indicators of Compromise
- .FCStd files (ZIP containers) whose inner Document.xml contains PropertyPythonObject entries with module attributes referencing unexpected packages such as os, subprocess, socket, or attacker-controlled paths.
- Child processes spawned by the FreeCAD binary that are inconsistent with normal modeling activity, for example shells, python invocations of unknown scripts, or network utilities.
- Outbound network connections initiated by the FreeCAD process shortly after a document open event.
Detection Strategies
- Inspect Document.xml inside untrusted FCStd archives for <PropertyPythonObject ... module="..."> values outside the FreeCAD standard workbench namespace.
- Hunt for process lineage where FreeCAD is the parent of interpreters, LOLBins, or persistence utilities.
- Alert on FreeCAD writing to autostart locations, cron entries, or user shell profile files.
Monitoring Recommendations
- Log and review file opens of .FCStd documents received from external sources or shared drives.
- Monitor for FreeCAD-initiated egress to non-corporate destinations, especially immediately after document load.
- Track FreeCAD version telemetry across endpoints to confirm rollout of the 1.1.2 update.
How to Mitigate CVE-2026-34789
Immediate Actions Required
- Upgrade all FreeCAD installations to version 1.1.2 or later using the official 1.1.2 release.
- Treat any .FCStd file from an untrusted source as executable content until endpoints are patched.
- Review recent FreeCAD sessions on shared workstations for anomalous child processes or outbound connections.
Patch Information
The fix is delivered in FreeCAD 1.1.2. Relevant upstream commits include 81b7392, 983037f, and e2dc6c8. The patches remove the exposed loadPickle() interface and constrain Restore() to import only modules whose file origin lies under directories registered in FreeCAD.__ModDirs__. See the GHSA-493w-pp4h-h77v advisory for full details.
Workarounds
- Do not open .FCStd files from unverified senders or public model repositories until version 1.1.2 is deployed.
- Run FreeCAD under a least-privilege user account, ideally in a sandbox or dedicated VM, to contain any executed payload.
- Where feasible, use application allowlisting or execution policies to prevent FreeCAD from spawning shells and interpreters.
# Verify installed FreeCAD version and upgrade path
freecad --version
# Expected output should include: FreeCAD 1.1.2 or later
# Example: constrain FreeCAD via a dedicated low-privilege user (Linux)
sudo useradd -m -s /bin/bash cad-sandbox
sudo -u cad-sandbox freecad /path/to/untrusted.FCStd
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

