Blue Yonder postgraas_server PostgreSQL Backend postgres_cluster_driver.py create_postgres_db sql injection
Description
A vulnerability, which was classified as critical, was found in Blue Yonder postgraas_server up to 2.0.0b2. Affected is the function _create_pg_connection/create_postgres_db of the file postgraas_server/backends/postgres_cluster/postgres_cluster_driver.py of the component PostgreSQL Backend Handler. The manipulation leads to sql injection. Upgrading to version 2.0.0 is able to address this issue. The patch is identified as 7cd8d016edc74a78af0d81c948bfafbcc93c937c. It is recommended to upgrade the affected component. VDB-234246 is the identifier assigned to this vulnerability.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Blue Yonder postgraas_server <=2.0.0b2 has a critical SQL injection in PostgreSQL backend handlers that allows attackers to execute arbitrary SQL.
Vulnerability
Overview
A critical SQL injection vulnerability exists in Blue Yonder's postgraas_server, a PostgreSQL-as-a-service toolkit, in versions up to and including 2.0.0b2. The flaw resides in the functions _create_pg_connection and create_postgres_db within the file postgraas_server/backends/postgres_cluster/postgres_cluster_driver.py. The root cause is the use of unsafe string formatting with user-supplied input when constructing SQL queries, bypassing proper parameterization [1][3].
Attack
Vector
The vulnerability is exploitable by an attacker who can provide crafted input to the PostgreSQL backend handler, likely through the REST API that accepts parameters like db_username and db_name. No authentication is explicitly mentioned as a barrier; the attack can be conducted over the network. The vulnerable code directly interpolates unsanitized values into SQL statements, allowing an attacker to inject arbitrary SQL commands [1][2][3].
Impact
Successful exploitation could allow an attacker to execute arbitrary SQL queries against the underlying PostgreSQL database. This could lead to unauthorized data access, modification, or deletion, as well as potential escalation of privileges within the database context. Given that postgraas_server manages database instances, an attacker could compromise the integrity and confidentiality of managed databases [1].
Mitigation
The issue is resolved in version 2.0.0, which was released alongside the commit 7cd8d016edc74a78af0d81c948bfafbcc93c937c. The fix replaces string formatting with parameterized queries using psycopg2's SQL and Identifier objects, preventing injection [3][4]. Users are strongly advised to upgrade to the latest version or apply the patch immediately.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
postgraas-serverPyPI | < 2.0.0 | 2.0.0 |
Affected products
3- Range: <=2.0.0b2
- Blue Yonder/postgraas_serverv5Range: 2.0.0b2
Patches
17cd8d016edc7Harden the database creation against SQL injections
3 files changed · +22 −13
postgraas_server/backends/postgres_cluster/postgres_cluster_driver.py+20 −13 modified@@ -1,5 +1,6 @@ import psycopg2 from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT +from psycopg2.sql import SQL, Identifier def _create_pg_connection(config): @@ -19,9 +20,9 @@ def _create_pg_connection(config): def check_db_or_user_exists(db_name, db_user, config): with _create_pg_connection(config) as con: with con.cursor() as cur: - cur.execute("SELECT 1 FROM pg_database WHERE datname='{}';".format(db_name)) + cur.execute("SELECT 1 FROM pg_database WHERE datname=%s;", (db_name, )) db_exists = cur.fetchone() is not None - cur.execute("SELECT 1 FROM pg_roles WHERE rolname='{}';".format(db_user)) + cur.execute("SELECT 1 FROM pg_roles WHERE rolname=%s;", (db_user, )) user = cur.fetchone() user_exists = user is not None return db_exists or user_exists @@ -33,23 +34,29 @@ def create_postgres_db(connection_dict, config): with _create_pg_connection(config) as con: con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) with con.cursor() as cur: - create_role = "CREATE USER {db_username} WITH PASSWORD '{db_pwd}';".format(**connection_dict) - drop_role = "DROP ROLE {db_username};".format(**connection_dict) - grant_role = 'GRANT {db_username} TO "{postgraas_user}";'.format( - db_username=connection_dict['db_username'], postgraas_user=get_normalized_username(config['username']) - ) - create_database = "CREATE DATABASE {db_name} OWNER {db_username};".format(**connection_dict) try: - cur.execute(create_role) - cur.execute(grant_role) + cur.execute(SQL("CREATE USER {} WITH PASSWORD %s;").format( + Identifier(connection_dict['db_username']), + ), ( + connection_dict['db_pwd'], + )) + cur.execute(SQL("GRANT {} TO {};").format( + Identifier(connection_dict['db_username']), + Identifier(get_normalized_username(config['username'])), + )) except psycopg2.ProgrammingError as e: raise ValueError(e.args[0]) # cleanup role in case database creation fails - # saidly 'CREATE DATABASE' cannot run inside a transaction block + # sadly 'CREATE DATABASE' cannot run inside a transaction block try: - cur.execute(create_database) + cur.execute(SQL("CREATE DATABASE {} OWNER {};").format( + Identifier(connection_dict['db_name']), + Identifier(connection_dict['db_username']), + )) except psycopg2.ProgrammingError as e: - cur.execute(drop_role) + cur.execute(SQL("DROP ROLE {};").format( + Identifier(connection_dict['db_username']), + )) raise ValueError(e.args[0])
tests/test_integration/backends/postgres_cluster/test_postgres_cluster_driver.py+1 −0 modified@@ -193,6 +193,7 @@ def test_create_postgres_instance_username_exists(self): backend_config) assert ("database or user already exists" in json.loads(response.get_data(as_text=True))['description']) is True + @pytest.mark.xfail(reason='Username now valid due to hardening against SQL injections.') def test_create_postgres_instance_bad_username(self): backend_config = CONFIGS[self.backend]['backend'] db_credentials = {
tests/test_integration/test_backend_behaviour.py+1 −0 modified@@ -167,6 +167,7 @@ def test_create_postgraas_twice(self): self.this_app.postgraas_backend.delete(db_entry) assert True + @pytest.mark.xfail(reason='Username now valid due to hardening against SQL injections.') def test_create_postgraas_bad_username(self): db_credentials = { "db_name": 'tests_postgraas_instance_name',
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/blue-yonder/postgraas_server/commit/7cd8d016edc74a78af0d81c948bfafbcc93c937cghsapatchWEB
- github.com/blue-yonder/postgraas_server/releases/tag/v2.0.0ghsapatchWEB
- github.com/advisories/GHSA-vghm-8cjp-hjw6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-25088ghsaADVISORY
- vuldb.comghsasignaturepermissions-requiredWEB
- vuldb.comghsavdb-entrytechnical-descriptionWEB
News mentions
0No linked articles in our index yet.