GHSA-8q6g-vjhf-jp8m

Suggest an improvement
Source
https://github.com/advisories/GHSA-8q6g-vjhf-jp8m
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-8q6g-vjhf-jp8m/GHSA-8q6g-vjhf-jp8m.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-8q6g-vjhf-jp8m
Aliases
Published
2026-09-22T19:45:51Z
Modified
2026-09-22T20:00:05Z
Severity
  • 7.5 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVSS Calculator
Summary
psd-tools composite/numpy has uncontrolled memory allocation via crafted PSD geometry
Details

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.

Database specific
{
    "cwe_ids":  [
        "CWE-789"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-09-22T19:45:51Z",
    "nvd_published_at":  null,
    "severity":  "HIGH"
}
References

Affected packages

PyPI / psd-tools

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
1.17.4

Affected versions

0.*
0.1.1
0.1.2
0.1.3
0.1.4
0.2
0.5
0.6
0.7
0.7.1
0.8
0.8.1
0.8.2
0.8.3
0.8.4
0.9
0.9.1
0.10
1.*
1.0
1.1
1.2
1.3
1.4
1.8.8
1.8.9
1.8.10
1.8.11
1.8.12
1.8.13
1.8.14
1.8.15
1.8.16
1.8.17
1.8.18
1.8.19
1.8.20
1.8.21
1.8.22
1.8.23
1.8.24
1.8.25
1.8.26
1.8.27
1.8.28
1.8.29
1.8.30
1.8.31
1.8.32
1.8.33
1.8.34
1.8.35
1.8.36
1.8.37
1.8.38
1.9.0
1.9.1
1.9.2
1.9.3
1.9.4
1.9.5
1.9.6
1.9.7
1.9.8
1.9.9
1.9.10
1.9.11
1.9.12
1.9.13
1.9.14
1.9.15
1.9.16
1.9.17
1.9.18
1.9.19
1.9.20
1.9.21
1.9.22
1.9.23
1.9.24
1.9.26
1.9.27
1.9.28
1.9.29
1.9.30
1.9.31
1.9.32
1.9.33
1.9.34
1.10.0
1.10.1
1.10.2
1.10.3
1.10.4
1.10.5
1.10.6
1.10.7
1.10.8
1.10.9
1.10.10
1.10.11
1.10.12
1.10.13
1.11.0
1.11.1
1.12.0
1.12.1
1.12.2
1.13.0
1.13.1
1.14.0
1.14.1
1.14.2
1.14.3
1.15.0.post1
1.16.0
1.17.0
1.17.1
1.17.2
1.17.3

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-8q6g-vjhf-jp8m/GHSA-8q6g-vjhf-jp8m.json"