{"items":[{"id":"NVI-00009037","kind":"vulnerability","title":"rucio has an Authorization Bypass on REST API endpoint for signing URLs","revision":1,"unknowns":["Customer inventory, deployment, reachability and exploitation have not been inspected."],"lifecycle":"active","identifiers":["GHSA-5j9r-fx4x-rpvg","CVE-2026-58273"],"plain_summary":"GitHub lists this reviewed advisory for rucio, rucio, rucio. Published version ranges and source prerequisites are shown below; this is not an inspection of a visitor’s application.","review_status":"source_listed","control_topics":[],"public_actions":[{"summary":"Identify the exact component and deployed version, examine the linked publisher’s conditions, and retain evidence of any mitigation.","source_ids":["sr-83b9ee10edfdbbd1e1368ff90f120722"],"action_type":"investigate","limitations":"Confirm current vendor support, compatibility and deployment evidence. This report has not tested a fix in your system.","current_supported_target":null}],"schema_version":"1.1.0","source_metrics":[{"kind":"CVSS","as_of":"2026-10-28T19:50:05.000Z","value":"8.8 high","meaning":"GitHub source severity; exploitability and local consequence require separate evidence.","source_id":"sr-83b9ee10edfdbbd1e1368ff90f120722"}],"why_it_matters":"Published affected context helps an owner decide what evidence to gather. This report has not examined your application.","related_sources":[{"id":"sr-83b9ee10edfdbbd1e1368ff90f120722","url":"https://github.com/advisories/GHSA-5j9r-fx4x-rpvg","basis":"vendor_advisory","notes":"GitHub Advisory Database; CC-BY-4.0. Each advisory links its original attribution. Null normalizes fields.","title":"GHSA-5j9r-fx4x-rpvg","publisher":"GitHub Advisory Database","observed_at":"2026-10-31T21:56:36.327Z"}],"affected_context":[{"certainty":"source_listed","source_ids":["sr-83b9ee10edfdbbd1e1368ff90f120722"],"technology":"rucio","known_exclusions":[],"conditions_summary":"## Summary\nThe `/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.\n\n## Details\n`SignURL.get()` takes the authorization principal from a request header and\nnever uses the token-authenticated identity:\n\n```python\n# lib/rucio/web/rest/flaskapi/v1/credentials.py\naccount = request.headers.get('X-Rucio-Account', default=None)     # L165  (attacker-controlled)\n...\nresult = get_signed_url(account, rse=rse, service=service,         # L194\n                        operation=operation, url=url, lifetime=lifetime, vo=vo)\n```\n\nThe gateway then uses that header value as the `issuer` for the permission check:\n\n```python\n# lib/rucio/gateway/credential.py\nauth_result = permission.has_permission(issuer=account, vo=vo,     # L57\n                                        action='","public_affected_ranges":[">= 1.16.1, < 35.9.0"]},{"certainty":"source_listed","source_ids":["sr-83b9ee10edfdbbd1e1368ff90f120722"],"technology":"rucio","known_exclusions":[],"conditions_summary":"## Summary\nThe `/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.\n\n## Details\n`SignURL.get()` takes the authorization principal from a request header and\nnever uses the token-authenticated identity:\n\n```python\n# lib/rucio/web/rest/flaskapi/v1/credentials.py\naccount = request.headers.get('X-Rucio-Account', default=None)     # L165  (attacker-controlled)\n...\nresult = get_signed_url(account, rse=rse, service=service,         # L194\n                        operation=operation, url=url, lifetime=lifetime, vo=vo)\n```\n\nThe gateway then uses that header value as the `issuer` for the permission check:\n\n```python\n# lib/rucio/gateway/credential.py\nauth_result = permission.has_permission(issuer=account, vo=vo,     # L57\n                                        action='","public_affected_ranges":[">= 36.0.0rc1, < 38.6.0"]},{"certainty":"source_listed","source_ids":["sr-83b9ee10edfdbbd1e1368ff90f120722"],"technology":"rucio","known_exclusions":[],"conditions_summary":"## Summary\nThe `/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.\n\n## Details\n`SignURL.get()` takes the authorization principal from a request header and\nnever uses the token-authenticated identity:\n\n```python\n# lib/rucio/web/rest/flaskapi/v1/credentials.py\naccount = request.headers.get('X-Rucio-Account', default=None)     # L165  (attacker-controlled)\n...\nresult = get_signed_url(account, rse=rse, service=service,         # L194\n                        operation=operation, url=url, lifetime=lifetime, vo=vo)\n```\n\nThe gateway then uses that header value as the `issuer` for the permission check:\n\n```python\n# lib/rucio/gateway/credential.py\nauth_result = permission.has_permission(issuer=account, vo=vo,     # L57\n                                        action='","public_affected_ranges":[">= 39.0.0rc1, < 41.0.0rc1"]}],"null_published_at":"2026-10-31T22:13:31.268Z","source_updated_at":"2026-10-28T19:50:05.000Z","source_disclosed_at":"2026-10-28T19:50:05.000Z","is_synthetic_fixture":false,"null_last_reviewed_at":null,"public_change_summary":"First indexed by Null; source disclosure date is shown separately.","null_first_observed_at":"2026-10-31T21:56:36.327Z"}],"next_cursor":null,"snapshot_revision":"42594"}