Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

psd-tools composite/numpy has uncontrolled memory allocation via crafted PSD geometryGHSA-8q6g-vjhf-jp8m

HIGHFix: psd-tools/psd-tools@a3d9a53

GHSA-8q6g-vjhf-jp8m is a high-severity (CVSS 7.5) CWE-789 vulnerability in psd-tools. A fix is available for psd-tools — see the affected versions and patch details below.

Also known asCVE-2026-59991PYSEC-2026-4139
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 24, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for GHSA-8q6g-vjhf-jp8m.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs43th percentile — riskier than 43% of all scored CVEsHighest risk
0.02%0.35%0.68%1.02%0.5%0.5%Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

GHSA-8q6g-vjhf-jp8m by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐍psd-tools

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

PSDImage.composite() (and .numpy()) allocate the output image buffer from the PSD's header geometry (width × height × channels × depth, and per-layer rectangles) before validating those values against the actual file contents. A tiny crafted PSD declaring huge dimensions causes a multi-gigabyte allocation. Critically, composite() then returns a (black) image with only a warning, no exception is raised, so a caller cannot detect or guard against it.

Impact

On psd-tools 1.17.2 (latest), default usage, a 49-byte PSD makes composite() commit ~3 GB and return successfully (warning only); .numpy() reaches ~7.5 GB, and the per-layer rectangle is a second lever (up to ~32 GB), all from an input under 100 bytes (input-to-commit amplification over 1000×). Because the buffer is committed before validation and no exception is thrown, any service that composites untrusted PSDs is exposed to denial of service: on a host with less RAM than the attacker-declared geometry the allocation is an unrecoverable OOM-kill.

Steps to reproduce

# pip install psd-tools==1.17.2
from psd_tools import PSDImage
psd = PSDImage.open("psd-psdtools-grammar-d23.psd")
psd.composite()   # commits ~3 GB from a 49-byte file and returns (warning only)

PoC (49 bytes), reconstruct with:

base64 -d > psd-psdtools-grammar-d23.psd <<'EOF'
OEJQUwABAAAAAAAAAAYAACg4AAAXTAAIAAMAAAAAAAAAAAAAAAAAAUNIUIFU+yQtDw==
EOF

Verify:

7d8ebf03a54393cb0359ecf4b676d1b08c9a8c6afdd06671ef406d6893cce826  psd-psdtools-grammar-d23.psd

Root cause

The composite/numpy buffer is sized from the declared image (and per-layer) dimensions and channel/depth without checking them against the available data length or a sane maximum.

Suggested fix

Validate the declared dimensions, channel count, and per-layer rectangles against the actual file length (and a configurable maximum pixel/byte budget) before allocating; raise an error on overflow instead of committing the buffer and returning a black image.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIpsd-toolsall versions1.17.4pip install --upgrade 'psd-tools==1.17.4'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for psd-tools, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update psd-tools to 1.17.4 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-8q6g-vjhf-jp8m is resolved across your whole dependency graph.

  3. Workarounds

    Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.

Frequently Asked Questions

### Summary `PSDImage.composite()` (and `.numpy()`) allocate the output image buffer from the PSD's header geometry (width × height × channels × depth, and per-layer rectangles) before validating those values against the actual file contents. A tiny crafted PSD declaring huge dimensions causes a multi-gigabyte allocation. Critically, `composite()` then returns a (black) image with only a warning, no exception is raised, so a caller cannot detect or guard against it. ### Impact On psd-tools 1.17.2 (latest), default usage, a 49-byte PSD makes `composite()` commit ~3 GB and return successfully (
O3 Security · Impact-Aware SCA

Is GHSA-8q6g-vjhf-jp8m in your dependencies?

Find it across PyPI, including transitive dependencies.

psd-tools composite/numpy has uncontrolled memory…