highCVE-2026-54917Aug 12, 2026

CVE-2026-54917: SeaweedFS Path Traversal in S3 and Iceberg REST Gateways

Shubham Kandhare
Security Engagement Manager, SecureLayer7

A missing path segment check in SeaweedFS's S3 and Iceberg REST gateways lets any caller use dot-dot sequences in the URL to read or write objects in buckets they were never given access to.

Packagegithub.com/seaweedfs/seaweedfs
Ecosystemgo
Affected< 0.0.0-20260526080459-dd1b4287899e
Fixed in0.0.0-20260526080459-dd1b4287899e
CVE-2026-54917: SeaweedFS Path Traversal in S3 and Iceberg REST Gateways

The problem

The S3 and Iceberg REST gateway routers are built with mux.NewRouter().SkipClean(true), which tells gorilla/mux to leave .. segments untouched in the matched URL. A request like GET /bucket-A/../evil-bucket/key is routed with bucket=bucket-A and object=../evil-bucket/key.

The captured object key is then passed to util.JoinPath (S3) or path.Join (Iceberg), which collapse the .. server-side. The real I/O lands in evil-bucket, not bucket-A. With auth enabled this also breaks IAM: the policy check sees bucket-A while storage operates on evil-bucket, a classic confused-deputy that lets a low-privilege tenant reach another tenant's data.

Proof of concept

A working proof-of-concept for CVE-2026-54917 in github.com/seaweedfs/seaweedfs, with the exact payload below.

http
GET /bucket-A/../evil-bucket/secret.txt HTTP/1.1
Host: <seaweedfs-s3-gateway>

# Percent-encoded variant (also works, gorilla/mux decodes before matching):
GET /bucket-A/%2e%2e/evil-bucket/secret.txt HTTP/1.1
Host: <seaweedfs-s3-gateway>

gorilla/mux with SkipClean(true) preserves raw .. segments in path variables, so the router never sees a cleaned path. util.JoinPath and path.Join then resolve the traversal server-side, silently redirecting I/O to the attacker-chosen bucket.

The %2e%2e variant works identically because gorilla/mux percent-decodes captured variables before returning them, and NormalizeObjectKey folds backslashes to forward slashes before the path is used, making ..\ equivalent as well.

The patch (PR #9687, commit dd1b428) adds a validation middleware to both gateway routers. It inspects every mux path variable before any handler runs and rejects the request with a 400 if any variable contains a . or .. path segment, a NUL byte, an embedded slash or backslash in a single-segment slot, or an empty value.

CWE-22.

The fix

Upgrade to SeaweedFS 4.30 or later (Go module pseudo-version 0.0.0-20260526080459-dd1b4287899e). If an immediate upgrade is not possible, place a reverse proxy in front of the gateway that normalizes request paths and rejects any path containing .., %2e%2e, or backslash sequences.

Do not rely on enableAuth=false deployments being protected by any other control.

Reported by Denis Abashkin (@dadbravo).

References: [1][2][3][4][5]

Related research