Live › vulnerability › CVE-2026-58273
Go to dashboardRucio's /credentials/signurl endpoint takes the account from a client-supplied X-Rucio-Account header instead of the authenticated token, so setting it to root passes the root-only check. An attacker with any valid token can get presigned read, write or delete URLs for arbitrary objects on cloud-backed RSEs, signed with the server's stored S3, GCS or Swift credentials.
Summary written from the sources below. Check the originals before acting.
First seen by InfraStack 2026-10-28 19:51 UTC. All times on this page are UTC.
Rucio deployments that expose the REST API to users holding any valid token and that have at least one S3, GCS or Swift RSE. Deployments with only non-cloud RSEs, or with the API reachable only by fully trusted operators, are less exposed. Multi-VO deployments also face cross-tenant access through the X-Rucio-VO header.
| Product | Ecosystem | Affected | Fixed in |
|---|---|---|---|
| rucio | pypi | >= 1.16.1, < 35.9.0 | 35.9.0 |
| rucio | pypi | >= 36.0.0rc1, < 38.6.0 | 38.6.0 |
| rucio | pypi | >= 39.0.0rc1, < 41.0.0rc1 | 41.0.0rc1 |
pip show rucio on the Rucio server and compare the version against the fixed releases./credentials/signurl that carry an X-Rucio-Account header.35.9.0 on the 35.x line, 38.6.0 on the 38.x line, or 41.0.0rc1 on the 39 to 41 line.X-Rucio-Account header at the reverse proxy until the upgrade is in place.Each row is the first time that source carried this signal. The analyst’s rows are its own findings.
The /credentials/signurl endpoint decides authorization from the client-supplied X-Rucio-Account HTTP header instead of the authenticated token's account. Any client holding any valid auth token (even a low-privilege account they legitimately own) can send X-Rucio-Account: root to pass the root-only permission check and have the Rucio server mint a presigned read / write / delete URL for an arbitrary object, signed with the RSE's stored S3 / GCS / Swift credentials.
SignURL.get() takes the authorization principal from a request header and
never uses the token-authenticated identity:
# lib/rucio/web/rest/flaskapi/v1/credentials.py
account = request.headers.get('X-Rucio-Account', default=None) # L165 (attacker-controlled)
...
result = get_signed_url(account, rse=rse, service=service, # L194
operation=operation, url=url, lifetime=lifetime, vo=vo)
The gateway then uses that header value as the issuer for the permission check:
# lib/rucio/gateway/credential.py
auth_result = permission.has_permission(issuer=account, vo=vo, # L57
action='get_signed_url', kwargs=kwargs, ...)
and the permission function is root-only:
# lib/rucio/core/permission/generic.py
def perm_get_signed_url(issuer, kwargs, session):
return _is_root(issuer) # _is_root(x) -> x.external == 'root'
InternalAccount('root', vo).external == 'root' unconditionally, so the gate passes whenever the header is root. The endpoint is on AuthenticatedBlueprint, whose before_request hook validates the token and sets request.environ['issuer'] from the token — but nothing ever compares X-Rucio-Account to it:
# lib/rucio/web/rest/flaskapi/v1/common.py (request_auth_env)
flask.request.environ['issuer'] = auth.get('account') # L168 (the real account; unused by SignURL)
This is anomalous: every other authenticated handler derives the account from request.environ['issuer']; credentials.py is the only one that trusts the header. Additionally, core.credential.get_signed_url never checks that the supplied url's host/bucket belongs to the target RSE, so even a legitimate root caller gets an arbitrary-object signing oracle. In multi-VO the VO is also read from the X-Rucio-VO header, allowing cross-tenant targeting.
Request (any valid token + spoofed account):
GET /credentials/signurl?rse=<cloudRSE>&svc=s3&op=delete&url=https://victim-bucket.s3.amazonaws.com/important/dataset.root HTTP/1.1
X-Rucio-Auth-Token: <any valid token, even a low-privilege account>
X-Rucio-Account: root
Accept: application/octet-stream
Response: 200 OK with a presigned DELETE URL the attacker replays directly against the storage backend.
A low-privilege Rucio user can read, overwrite, and delete arbitrary objects on any cloud-backed (S3/GCS/Swift) RSE using the server's stored credentials — enabling data exfiltration, tampering, and destruction, and cross-tenant access in multi-VO deployments.
Reported by seankohjs. Found via static analysis + manual verification.
This page as .md · .json · in your agent: get_signal("CVE-2026-58273")
GitHub Advisory Database, CC-BY 4.0. Posts quoted belong to their authors.