CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

CVE-2026-49836

mediumcovered by 1 sourcefirst seen 2026-07-09
psd-tools: arbitrary file write/read via smart-object path traversal Summary In psd-tools (all releases exposing the SmartObject API through v1.17.0), SmartObject.save() writes an embedded smart object to a path taken verbatim from the PSD file. Because that name is attacker-controlled and unsanitised, a tool that extracts embedded objects from an untrusted .psd can be made to write attacker-chosen bytes to an attacker-chosen path (absolute or ../-traversing), outside its intended output directory. A secondary issue in SmartObject.open() for external-kind smart objects allows the attacker-controlled fullPath descriptor to be used as an arbitrary file read path, enabling exfiltration of the read content to the controlled write destination. Both issues are fixed in v1.17.1. Details Write path — SmartObject.save() (primary) src/psd_tools/api/smart_object.py:170-179 (tag v1.17.0): def save(self, filename: str | None = None) -> None: if filename is None: filename = self.filename # untrusted, straight from the file with open(filename, "wb") as f: f.write(self.data) # attacker-controlled bytes self.filename comes from the file with no validation — the filename property (:62-67) returns self._data.filename, set by the linked-layer parser at src/psd_tools/psd/linked_layer.py:100 (read_unicode_string(fp)). There is no basename, no absolute path rejection, and no .. filtering; the written contents (self.data) are likewise from the file, so the attacker controls both destination and content. Read path — SmartObject.open() / .data for external kind (secondary) For kind == "external", save() read file content via the data property, which called open() with no external_dir constraint. The fullPath descriptor embedded in the PSD was then used verbatim as the source path, enabling an attacker-crafted PSD to cause save(directory="/safe/out") to read an arbitrary readable file (e.g. /etc/passwd) and write its contents to the output directory. Proof of concept Standalone, a

⚡ Watch CVE-2026-49836

Get an email if CVE-2026-49836 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.

Advisory coverage (1)

External references

NVD record for CVE-2026-49836

CVE.org record

Embed the live status

CVE-2026-49836 live status badge — this badge updates automatically when the KEV or exploit status changes. How to embed it →

[![CVE-2026-49836 status](https://www.csirts.com/badge/CVE-2026-49836)](https://www.csirts.com/cve/CVE-2026-49836)