S3-Proxy has Security Issues in its Resource Path Matching Implementation
Date: 2026-05
Affected: go/github.com/oxyno-zeta/s3-proxy
Attack vector: auth-bypass
Category: vulnerability-disclosure
Severity: Critical
CVE: CVE-2026-42882
CWE: CWE-22
CWE-863
CVSS: 9.4 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L)

## Background The original concern is functional: a resource pattern should treat a percent-encoded segment like some%2Fvalue as a single opaque token rather than splitting it into two path segments at the decoded /. Investigation into why %2F was being decoded and how routes matched against the result surfaced three related security issues, documented below. Rather than landing a fix directly, the problem space warrants discussion first. Different fixes carry different compliance and compatibility tradeoffs, and every viable option is a breaking change in some form. Aligning on a direction before committing to an implementation is the safer path. ## Root cause: two different path representations Go's `net/http` decodes percent-encoded characters when it parses an incoming URL: `%2F` becomes `/` in `r.URL.Path`, while the original encoded form is preserved in `r.URL.RawPath`. Two different parts of s3-proxy use different fields: - The **auth middleware** calls `r.URL.RequestURI()`, which returns the encoded form (from `RawPath` when available). It sees `%2F` as literal characters, not as path separators. - The **bucket handler** reads `r.URL.Path` to build the S3 key. It sees the decoded form, where `%2F` has already become `/`. All three issues stem from this mismatch, combined with how glob patterns are compiled. The examples below use PUT for concreteness, but the auth bypass applies to any HTTP method — a config that restricts GET or DELETE on a namespace is e


Mitigations:

Architectural layers (MAESTRO):