GHSA-VCWH-PFF9-64CC
Vulnerability from github – Published: 2026-01-08 20:36 – Updated: 2026-01-08 20:36Summary
The ImportIam admin API validates permissions using ExportIAMAction instead of ImportIAMAction, allowing a principal with export-only IAM permissions to perform import operations. Since importing IAM data performs privileged write actions (creating/updating users, groups, policies, and service accounts), this can lead to unauthorized IAM modification and privilege escalation.
Details
In ImportIam, the authorization check is implemented as follows:
validate_admin_request(
&req.headers,
&cred,
owner,
false,
vec![Action::AdminAction(AdminAction::ExportIAMAction)],
).await?;
However, this code resides in the Import IAM operation (struct ImportIam {}), which performs state-changing IAM writes.
The expected behavior is to validate against AdminAction::ImportIAMAction (or an equivalent import-specific admin action), not ExportIAMAction.
PoC
Prerequisites
- A RustFS deployment with IAM enabled.
- An IAM user or role that has Export IAM permission but does not have Import IAM or full admin permissions.
- Access credentials for that user.
Steps
- Create or obtain an IAM principal with permission equivalent to:
AdminAction::ExportIAMAction
and without Import IAM privileges.
-
Prepare a valid IAM import ZIP archive containing, for example:
-
A new policy granting administrative permissions
-
A user or service account bound to that policy
-
Send a request to the Import IAM endpoint (the same endpoint handled by
ImportIam::call), authenticating with the export-only credentials. -
Observe that:
-
The request passes authorization.
- IAM entities from the archive are created or modified successfully.
Expected Result
- The request should be rejected with an authorization error (e.g., AccessDenied).
Actual Result
- The request succeeds, and IAM state is modified.
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "rustfs"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.0.0-alpha.79"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-22042"
],
"database_specific": {
"cwe_ids": [
"CWE-285"
],
"github_reviewed": true,
"github_reviewed_at": "2026-01-08T20:36:17Z",
"nvd_published_at": "2026-01-08T15:15:45Z",
"severity": "MODERATE"
},
"details": "### Summary\n\nThe `ImportIam` admin API validates permissions using **`ExportIAMAction`** instead of **`ImportIAMAction`**, allowing a principal with *export-only* IAM permissions to perform *import* operations. Since importing IAM data performs privileged **write** actions (creating/updating users, groups, policies, and service accounts), this can lead to **unauthorized IAM modification and privilege escalation**.\n\n---\n\n### Details\n\nIn `ImportIam`, the authorization check is implemented as follows:\n\n```rust\nvalidate_admin_request(\n \u0026req.headers,\n \u0026cred,\n owner,\n false,\n vec![Action::AdminAction(AdminAction::ExportIAMAction)],\n).await?;\n```\n\nHowever, this code resides in the **Import IAM** operation (`struct ImportIam {}`), which performs **state-changing IAM writes**.\n\nThe expected behavior is to validate against **`AdminAction::ImportIAMAction`** (or an equivalent import-specific admin action), not `ExportIAMAction`.\n\n---\n\n### PoC\n\n**Prerequisites**\n\n1. A RustFS deployment with IAM enabled.\n2. An IAM user or role that has **Export IAM** permission but **does not** have Import IAM or full admin permissions.\n3. Access credentials for that user.\n\n**Steps**\n\n1. Create or obtain an IAM principal with permission equivalent to:\n\n ```\n AdminAction::ExportIAMAction\n ```\n\n and without Import IAM privileges.\n\n2. Prepare a valid IAM import ZIP archive containing, for example:\n\n * A new policy granting administrative permissions\n * A user or service account bound to that policy\n\n3. Send a request to the Import IAM endpoint (the same endpoint handled by `ImportIam::call`), authenticating with the export-only credentials.\n\n4. Observe that:\n\n * The request passes authorization.\n * IAM entities from the archive are created or modified successfully.\n\n**Expected Result**\n\n* The request should be rejected with an authorization error (e.g., AccessDenied).\n\n**Actual Result**\n\n* The request succeeds, and IAM state is modified.",
"id": "GHSA-vcwh-pff9-64cc",
"modified": "2026-01-08T20:36:17Z",
"published": "2026-01-08T20:36:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/rustfs/rustfs/security/advisories/GHSA-vcwh-pff9-64cc"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-22042"
},
{
"type": "PACKAGE",
"url": "https://github.com/rustfs/rustfs"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P",
"type": "CVSS_V4"
}
],
"summary": "RustFS has IAM Incorrect Authorization in ImportIam that Allows Privilege Escalation"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.