Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🦀
🦀 crates.io
Not in CISA KEV
MEDIUM severity

CVE-2026-39360 rustfs

MEDIUM

CVE-2026-39360 is a medium-severity (CVSS 4.3) CWE-862 vulnerability in rustfs. No vendor fix is recorded yet; mitigation options are listed below.

RustFS has an authorization bypass in multipart UploadPartCopy enables cross-bucket object exfiltration

Published
Apr 8, 2026
Updated
Apr 10, 2026
Affected
1 pkg
Patched
None yet
Exploits
None indexed
Exploitation data as of Sep 19, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-39360.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs10th percentile — riskier than 10% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-39360 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,238 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🦀rustfs

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects crates.io packages — download data is not available via public APIs for these ecosystems.

Description

RustFS contains a missing authorization check in the multipart copy path (UploadPartCopy). A low-privileged user who cannot read objects from a victim bucket can still exfiltrate victim objects by copying them into an attacker-controlled multipart upload and completing the upload.

This breaks tenant isolation in multi-user / multi-tenant deployments.

Impact

Unauthorized cross-bucket / cross-tenant data exfiltration (Confidentiality: High).

An attacker with only minimal permissions on their own bucket (multipart upload + Put/Get on destination objects) can copy and retrieve objects from a victim bucket without having s3:GetObject (or equivalent) permission on the source.

In the attached PoC, the attacker successfully exfiltrates a 5MB private object and proves integrity via matching SHA256 and size.

Threat Model (Realistic)

  • Victim tenant/user owns a bucket (e.g., victim-bucket-*) and stores private objects (e.g., private/finance_dump.bin).
  • Attacker tenant/user has no permissions on the victim bucket:
    • cannot ListObjects, HeadObject, GetObject, or CopyObject from the victim bucket.
  • Attacker has minimal permissions only on attacker bucket:
    • CreateMultipartUpload, UploadPart, UploadPartCopy, CompleteMultipartUpload, AbortMultipartUpload,
    • and PutObject/GetObject for objects in attacker bucket.
  • Despite this, attacker can exfiltrate victim objects via multipart copy.

Root Cause Analysis

The access control layer fails open for multipart copy-related operations:

File: rustfs/src/storage/access.rs

  • abort_multipart_upload() returns Ok(()) without authorization (L435–437)
  • complete_multipart_upload() returns Ok(()) without authorization (L442–444)
  • upload_part_copy() returns Ok(()) without authorization (L1446–1448)

In contrast, copy_object() correctly enforces authorization:

  • source GetObject authorization (L469)
  • destination PutObject authorization (L478)

The multipart copy implementation reads the source object directly:

File: rustfs/src/app/multipart_usecase.rs

  • store.get_object_reader(&src_bucket, &src_key, ...) (L959–962)

Because upload_part_copy() does not enforce source GetObject authorization, the server reads and copies victim data even when the requester lacks permission.

Affected Versions

  • Tested vulnerable on: main @ c1d5106acc3480c275a52344df84633bb6dcd8f0
  • Git describe: 1.0.0-alpha.86-3-gc1d5106a

The fail-open authorization behavior for UploadPartCopy was introduced in:

  • Commit: 09ea11c13 (per git blame on rustfs/src/storage/access.rs:1443-1448)

Affected range (recommended wording):

  • All versions from commit 09ea11c13 through c1d5106acc3480c275a52344df84633bb6dcd8f0 (and likely any releases containing those commits) until a fix is applied.

Package version (Cargo metadata)

  • rustfs crate version in this tree: 0.0.5 (cargo metadata)

Proof of Concept (PoC) – Real Commands + Verified Results

Files

Place the PoC script at the repository root:

Environment

RustFS running locally (Docker is simplest), listening on:

  • http://127.0.0.1:9000

Tools:

  • awscli, jq, awscurl

Steps to Reproduce

  1. Start RustFS (example):
docker compose -f docker-compose-simple.yml up -d
  1. Run the PoC and save output:
chmod +x poc_uploadpartcopy_exfil_v3.sh
./poc_uploadpartcopy_exfil_v3.sh | tee poc_v3_output.txt

Attachments

Expected Behavior

  • Attacker operations against victim bucket should be denied:

    • ListObjects -> AccessDenied
    • HeadObject -> AccessDenied
    • GetObject -> AccessDenied
    • CopyObject -> AccessDenied
  • UploadPartCopy from victim -> attacker multipart should also be denied.

Actual Behavior

  • All direct operations against victim are denied (as expected),
  • but UploadPartCopy succeeds, and attacker retrieves the copied object from attacker bucket.

Observed PoC Output

Victim uploads a private object:

  • size: 5,242,880 bytes
  • sha256: fda018db1da9d8f4c1b287c75943384a3b4ede391ec156039b6d94e17d6ad68f

Attacker exfiltrates it via multipart copy:

  • stolen size: 5,242,880 bytes
  • stolen sha256: fda018db1da9d8f4c1b287c75943384a3b4ede391ec156039b6d94e17d6ad68f

Proof:

  • hashes and sizes match (victim == stolen) -> unauthorized cross-bucket read confirmed.

Network Evidence (Redacted)

The debug log shows a successful request with:

  • HTTP method: PUT
  • destination: /<attacker-bucket>/<dst-key>?partNumber=1&uploadId=...
  • header: x-amz-copy-source: <victim-bucket>/private/finance_dump.bin
  • response: HTTP/1.1 200 with <CopyPartResult><ETag>...</ETag>...</CopyPartResult>

Fix

Implement authorization checks equivalent to copy_object() for multipart copy paths:

  • upload_part_copy:

    • enforce source GetObject authorization on x-amz-copy-source
    • enforce destination PutObject authorization on the target object
    • (recommended) apply the same tag-condition enforcement used by copy_object() on the source.
  • complete_multipart_upload:

    • enforce destination PutObject authorization
  • abort_multipart_upload:

    • enforce appropriate multipart permission (or destination PutObject as a safe boundary)

Affected Packages

1 total
EcosystemPackageVulnerable rangeFix
🦀crates.iorustfsall versionsNo fix

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for rustfs, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Remediation status

    No patched version of rustfs has shipped for CVE-2026-39360 yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.

  3. Mitigate without a patch

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-39360 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-39360. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

RustFS contains a missing authorization check in the multipart copy path (`UploadPartCopy`). A low-privileged user who cannot read objects from a victim bucket can still exfiltrate victim objects by copying them into an attacker-controlled multipart upload and completing the upload. This breaks tenant isolation in multi-user / multi-tenant deployments. ## Impact **Unauthorized cross-bucket / cross-tenant data exfiltration (Confidentiality: High).** An attacker with only minimal permissions on their own bucket (multipart upload + Put/Get on destination objects) can copy and retrieve objects
O3 Security · Impact-Aware SCA

Is CVE-2026-39360 in your dependencies?

O3 Security finds CVE-2026-39360 across crates.io dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-39360: rustfs (Medium 4.3) | O3 Security