GHSA-5j9r-fx4x-rpvg: High severity pip/rucio vulnerability

Published Oct 28, 2026
·
Updated

Summary 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.

Details SignURL.get() takes the authorization principal from a request header and never uses the token-authenticated identity:

python lib/rucio/web/rest/flaskapi/v1/credentials.py account = request.headers.get('X-Rucio-Account', default=None) # L165 (attacker-controlled) ... result = getsignedurl(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:

python lib/rucio/gateway/credential.py authresult = permission.haspermission(issuer=account, vo=vo, # L57 action='getsignedurl', kwargs=kwargs, ...)

and the permission function is root-only:

python lib/rucio/core/permission/generic.py def permgetsignedurl(issuer, kwargs, session): return isroot(issuer) # isroot(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 beforerequest hook validates the token and sets request.environ['issuer'] from the token — but nothing ever compares X-Rucio-Account to it:

python lib/rucio/web/rest/flaskapi/v1/common.py (requestauthenv) 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.getsignedurl 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.

Proof of concept 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.

Impact 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.

Credit Reported by seankohjs. Found via static analysis + manual verification.

Affected Software

3 affected componentsFixes available
pip/rucio>=39.0.0rc1<41.0.0rc1
41.0.0rc1
pip/rucio>=36.0.0rc1<38.6.0
38.6.0
pip/rucio>=1.16.1<35.9.0
35.9.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/rucio to a version that resolves this vulnerability.

    Fixed in 41.0.0rc1
  2. Upgrade

    Upgrade pip/rucio to a version that resolves this vulnerability.

    Fixed in 38.6.0
  3. Upgrade

    Upgrade pip/rucio to a version that resolves this vulnerability.

    Fixed in 35.9.0

Event History

Oct 28, 2026
Advisory Published
via GitHub·07:50 PM
Data Sourced
via GitHub·07:50 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What does an attacker need to exploit this issue?

The attacker needs any valid Rucio authentication token, including one belonging to a legitimately owned low-privilege account. They can then supply X-Rucio-Account: root to satisfy the root-only permission check.

2

What can an attacker do with a successfully obtained signed URL?

They can obtain a presigned URL for read, write, or delete operations. The URL is signed using the affected RSE's stored S3, GCS, or Swift credentials.

3

Is the requested object restricted to data the token holder is otherwise allowed to access?

No. The endpoint can mint a signed URL for an arbitrary object because authorization is evaluated using the client-controlled account header rather than the token-authenticated account.

4

Does exploitation require another user to take an action?

No user interaction is required. The attacker can make the request directly over the network using their valid token and a forged account header.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203