Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2025-13709

CVE-2025-13709: Tencent TFace RCE Vulnerability

CVE-2025-13709 is a remote code execution vulnerability in Tencent TFace's restore_checkpoint function caused by unsafe deserialization. Attackers can execute arbitrary code as root. Learn about technical details, impact, and mitigation.

Published:

CVE-2025-13709 Overview

CVE-2025-13709 is a deserialization of untrusted data vulnerability [CWE-502] in Tencent TFace, an open-source face recognition research toolkit. The flaw resides in the restore_checkpoint function, which loads PyTorch model checkpoints without validating the contents. Attackers can craft a malicious checkpoint file that executes arbitrary code when the victim loads it. Successful exploitation grants code execution in the context of root. The issue was reported through the Zero Day Initiative as ZDI-CAN-27185.

Critical Impact

Loading a malicious .ckpt file with the unpatched restore_checkpoint function results in arbitrary code execution as root, allowing full host compromise on systems running Tencent TFace training or inference workflows.

Affected Products

  • Tencent TFace (all versions prior to commit 7b2eed297d43dcdd1e3d45bfdfc950478e3af5d9)
  • TFace attribute/M3DFEL/solver.py checkpoint resume path
  • TFace generation/uiface/main.py checkpoint restore path

Discovery Timeline

  • 2025-12-23 - CVE-2025-13709 published to NVD
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2025-13709

Vulnerability Analysis

The vulnerability stems from how Tencent TFace restores model checkpoints through the PyTorch torch.load API. Prior to the fix, torch.load was invoked without the weights_only=True argument. This causes PyTorch to deserialize the checkpoint using Python's pickle module, which permits arbitrary callable invocation during the unpickling process. An attacker who can supply a crafted model.ckpt or optimization.ckpt file gains code execution the moment the file is loaded. Because TFace workflows commonly run as root inside containers and on training servers, the resulting process inherits those privileges.

Root Cause

The root cause is unsafe deserialization in the restore_checkpoint static method and the args.resume code path. Both call sites passed user-controllable file paths directly to torch.load, which defaults to pickle-based deserialization. PyTorch's pickle reader honors __reduce__ methods inside the serialized object, so a malicious checkpoint can embed instructions to spawn shells, write files, or load native code during load.

Attack Vector

Exploitation requires user interaction. The target must download or be supplied with a malicious checkpoint file and resume training, fine-tune, or run inference using TFace. Distribution typically occurs through pre-trained model sharing channels, supply-chain compromises of public model hubs, or social engineering against ML researchers.

python
# Patched code from generation/uiface/main.py
@staticmethod
def restore_checkpoint(model, optimizer, path, lr_scheduler=None):
    model_ckpt = torch.load(
-        os.path.join(path, "checkpoints", "model.ckpt"), map_location="cpu"
+        os.path.join(path, "checkpoints", "model.ckpt"), map_location="cpu", weights_only=True
    )
    optimization_ckpt = torch.load(
-        os.path.join(path, "checkpoints", "optimization.ckpt"), map_location="cpu"
+        os.path.join(path, "checkpoints", "optimization.ckpt"), map_location="cpu", weights_only=True
    )

    global_step = optimization_ckpt["global_step"]

Source: Tencent TFace patch commit 7b2eed2

Detection Methods for CVE-2025-13709

Indicators of Compromise

  • Unexpected child processes spawned by Python interpreters running TFace training scripts, particularly shells, curl, wget, or compilers.
  • Checkpoint files (model.ckpt, optimization.ckpt) originating from untrusted sources or recently downloaded from non-official mirrors.
  • Outbound network connections from training hosts to unfamiliar IPs immediately after a torch.load call.

Detection Strategies

  • Inspect TFace source for calls to torch.load that omit weights_only=True and flag them in code review or static analysis.
  • Monitor process trees for python parents spawning interactive shells or reverse-shell binaries on ML workstations and training nodes.
  • Use file integrity monitoring on checkpoint directories to detect unauthorized replacement of model.ckpt and optimization.ckpt.

Monitoring Recommendations

  • Enable EDR telemetry on ML training infrastructure and forward process, file, and network events to a centralized data lake for correlation.
  • Alert on root-owned Python processes initiating outbound connections to non-allowlisted hosts.
  • Audit pickle deserialization at runtime using tools such as fickling to scan checkpoints before loading.

How to Mitigate CVE-2025-13709

Immediate Actions Required

  • Update Tencent TFace to a revision that includes commit 7b2eed297d43dcdd1e3d45bfdfc950478e3af5d9 or rebase local forks onto the patched code.
  • Quarantine any checkpoints obtained from third parties until they are scanned for embedded pickle opcodes.
  • Run TFace processes as a non-root user inside a restricted container to reduce blast radius.

Patch Information

The vendor fix adds weights_only=True to every torch.load call inside attribute/M3DFEL/solver.py and generation/uiface/main.py. With this flag, PyTorch refuses to deserialize arbitrary Python objects and only loads tensor data. Apply the patch by pulling commit 7b2eed2 from the Tencent TFace repository or by manually adding weights_only=True to every torch.load invocation in downstream forks.

Workarounds

  • Wrap torch.load calls in a project-wide monkeypatch that injects weights_only=True until the upstream patch can be merged.
  • Validate checkpoint provenance using cryptographic signatures or hash allowlists before any load operation.
  • Execute training jobs inside sandboxed environments such as gVisor or rootless containers with no outbound network access.
bash
# Pin TFace to the patched commit and verify the fix
cd TFace
git fetch origin
git checkout 7b2eed297d43dcdd1e3d45bfdfc950478e3af5d9
grep -RIn "torch.load" attribute/ generation/ | grep -v "weights_only=True"
# The grep above must return no results after the patch is applied.

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.