# MinIO has an Unauthenticated Object Write via Missing Signature Verification in Unsigned-Trailer Uploads

MinIO's STREAMING-UNSIGNED-PAYLOAD-TRAILER path skips signature verification, letting anyone with a valid access key write arbitrary objects without the secret key.

- Payout: Research
- Severity: high
- Program: MinIO
- Found by: ddd
- Disclosed: 2026-04-14
- CVE: CVE-2026-40344
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-9c4q-hq6p-c237
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-9c4q-hq6p-c237
- Tags: area:cloud domain:cloud impact:integrity kind:research platform:ghsa sev:high tech:go technique:incomplete-fix technique:source-review vuln:access-control vuln:auth-bypass

**Target:** S3-compatible object storage server (PutObject/Snowball extract handlers)
**Root cause:** The authTypeStreamingUnsignedTrailer type added in PR #16484 was wired into PutObjectHandler/PutObjectPartHandler but never into PutObjectExtractHandler's switch, and the signature gate in newUnsignedV4ChunkedReader keys only on presence of the Authorization header while isPutActionAllowed also accepts X-Amz-Credential query credentials.
**Steps:**
1. Send PUT with `X-Amz-Content-Sha256: STREAMING-UNSIGNED-PAYLOAD-TRAILER` and `X-Amz-Meta-Snowball-Auto-Extract: true`
2. Include an `Authorization` header with a valid access key and a fabricated signature; PutObjectExtractHandler's switch has no case for the auth type so no signature check runs
3. Tar payload is extracted into the target bucket
4. Alternatively omit `Authorization` and pass credentials via `X-Amz-Credential` query param; `r.Header.Get(xhttp.Authorization) != ""` is false so doesSignatureMatch is never called
**How found:** Code review of the auth-type switch statements after the unsigned-trailer feature landed: noticed the new authTypeStreamingUnsignedTrailer case was added to PutObjectHandler and PutObjectPartHandler but absent from PutObjectExtractHandler, and that the signature gate used header presence rather than the credential source isPutActionAllowed actually trusts.
**Exploitation:** Attacker needs only a valid access key (e.g. default minioadmin or any key with WRITE on a bucket) plus bucket name; sends the crafted PUT and arbitrary objects land in any bucket without knowing the secret key.
**Insight:** When a new auth type is introduced, grep every handler that switches on auth type and every signature-gate boolean; gates keyed on header presence rather than the credential source the authz layer accepts (header vs query string) silently disable verification.

## Proof of concept (copied exactly from the original report)

**Vulnerable signature gate call in PutObjectHandler**

```
newUnsignedV4ChunkedReader(r, true, r.Header.Get(xhttp.Authorization) != "")
```

