GitHub Security Advisory: GHSA-mx42-j6wv-px98
Package: rustfs (RUST)
Severity: MODERATE (CVSS 4.3)
CWE: CWE-862: Missing Authorization
Vulnerable versions: <= 0.0.2
Patched in: unpatched

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

Details:
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