CVE-2026-12050
Full vulnerability record from the local CVENow database.
Description
SQL injection in pgAdmin 4's named restore point endpoint (POST /browser/server/restore_point/{gid}/{sid}). The user-supplied 'value' field was interpolated directly into the SQL string with str.format() instead of being passed as a bound parameter, allowing an authenticated pgAdmin user with a connected PostgreSQL session to inject additional statements through that endpoint. The injected SQL executes under the database role the user is already authenticated as. The defect does not cross a privilege boundary -- the user already has direct SQL access to that role through the Query Tool -- so the attacker gains no capability beyond what their database role already grants them. The marginal impact accounts for the fact that the injection path is not the documented SQL-execution interface, so a deployment that gates the Query Tool at the application layer could see SQL executed through a path it did not anticipate. Fix passes the restore point name as a bound parameter and schema-qualifies the function call as pg_catalog.pg_create_restore_point so a non-default search_path on the connection cannot redirect the call to a shadow definition. A regression test asserts the value arrives as a bound parameter and not spliced into the SQL string. This issue affects pgAdmin 4: from 1.0 before 9.16.
View original CVE JSON
{
"id": "CVE-2026-12050",
"sourceIdentifier": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"published": "2026-06-19T00:16:47.517",
"lastModified": "2026-10-25T23:10:00.167",
"vulnStatus": "Analyzed",
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "SQL injection in pgAdmin 4's named restore point endpoint (POST /browser/server/restore_point/{gid}/{sid}). The user-supplied 'value' field was interpolated directly into the SQL string with str.format() instead of being passed as a bound parameter, allowing an authenticated pgAdmin user with a connected PostgreSQL session to inject additional statements through that endpoint.\n\nThe injected SQL executes under the database role the user is already authenticated as. The defect does not cross a privilege boundary -- the user already has direct SQL access to that role through the Query Tool -- so the attacker gains no capability beyond what their database role already grants them. The marginal impact accounts for the fact that the injection path is not the documented SQL-execution interface, so a deployment that gates the Query Tool at the application layer could see SQL executed through a path it did not anticipate.\n\nFix passes the restore point name as a bound parameter and schema-qualifies the function call as pg_catalog.pg_create_restore_point so a non-default search_path on the connection cannot redirect the call to a shadow definition. A regression test asserts the value arrives as a bound parameter and not spliced into the SQL string.\n\nThis issue affects pgAdmin 4: from 1.0 before 9.16."
},
{
"lang": "es",
"value": "Inyección SQL en el endpoint de punto de restauración con nombre de pgAdmin 4 (POST /browser/server/restore_point/{gid}/{sid}). El campo ’value’ proporcionado por el usuario fue interpolado directamente en la cadena SQL con str.format() en lugar de ser pasado como un parámetro vinculado, permitiendo a un usuario autenticado de pgAdmin con una sesión de PostgreSQL conectada inyectar sentencias adicionales a través de ese endpoint.\n\nEl SQL inyectado se ejecuta bajo el rol de la base de datos con el que el usuario ya está autenticado. El defecto no cruza un límite de privilegios -- el usuario ya tiene acceso SQL directo a ese rol a través de la Herramienta de Consulta -- por lo que el atacante no obtiene ninguna capacidad más allá de lo que su rol de base de datos ya les otorga. El impacto marginal tiene en cuenta el hecho de que la ruta de inyección no es la interfaz documentada de ejecución de SQL, por lo que una implementación que restringe la Herramienta de Consulta en la capa de aplicación podría ver SQL ejecutado a través de una ruta que no anticipó.\n\nLa corrección pasa el nombre del punto de restauración como un parámetro vinculado y califica la llamada a la función con el esquema como pg_catalog.pg_create_restore_point para que un search_path no predeterminado en la conexión no pueda redirigir la llamada a una definición en la sombra. Una prueba de regresión afirma que el valor llega como un parámetro vinculado y no empalmado en la cadena SQL.\n\nEste problema afecta a pgAdmin 4: desde 1.0 hasta antes de 9.16."
}
],
"affected": [
{
"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"affectedData": [
{
"vendor": "pgadmin.org",
"product": "pgAdmin 4",
"defaultStatus": "unaffected",
"modules": [
"Server Node",
"Named Restore Point"
],
"programFiles": [
"https://github.com/pgadmin-org/pgadmin4/blob/master/web/pgadmin/browser/server_groups/servers/__init__.py"
],
"repo": "https://github.com/pgadmin-org/pgadmin4",
"versions": [
{
"version": "1.0",
"lessThan": "9.16",
"versionType": "custom",
"status": "affected"
}
]
}
]
}
],
"metrics": {
"cvssMetricV40": [
{
"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"type": "Secondary",
"cvssData": {
"version": "4.0",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"attackVector": "NETWORK",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"privilegesRequired": "LOW",
"userInteraction": "NONE",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "LOW",
"vulnAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"subAvailabilityImpact": "NONE",
"exploitMaturity": "NOT_DEFINED",
"confidentialityRequirement": "NOT_DEFINED",
"integrityRequirement": "NOT_DEFINED",
"availabilityRequirement": "NOT_DEFINED",
"modifiedAttackVector": "NOT_DEFINED",
"modifiedAttackComplexity": "NOT_DEFINED",
"modifiedAttackRequirements": "NOT_DEFINED",
"modifiedPrivilegesRequired": "NOT_DEFINED",
"modifiedUserInteraction": "NOT_DEFINED",
"modifiedVulnConfidentialityImpact": "NOT_DEFINED",
"modifiedVulnIntegrityImpact": "NOT_DEFINED",
"modifiedVulnAvailabilityImpact": "NOT_DEFINED",
"modifiedSubConfidentialityImpact": "NOT_DEFINED",
"modifiedSubIntegrityImpact": "NOT_DEFINED",
"modifiedSubAvailabilityImpact": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"valueDensity": "NOT_DEFINED",
"vulnerabilityResponseEffort": "NOT_DEFINED",
"providerUrgency": "NOT_DEFINED"
}
}
],
"cvssMetricV31": [
{
"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"type": "Secondary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
"baseScore": 4.3,
"baseSeverity": "MEDIUM",
"attackVector": "NETWORK",
"attackComplexity": "LOW",
"privilegesRequired": "LOW",
"userInteraction": "NONE",
"scope": "UNCHANGED",
"confidentialityImpact": "NONE",
"integrityImpact": "LOW",
"availabilityImpact": "NONE"
},
"exploitabilityScore": 2.8,
"impactScore": 1.4
},
{
"source": "[email protected]",
"type": "Primary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"baseScore": 8.8,
"baseSeverity": "HIGH",
"attackVector": "NETWORK",
"attackComplexity": "LOW",
"privilegesRequired": "LOW",
"userInteraction": "NONE",
"scope": "UNCHANGED",
"confidentialityImpact": "HIGH",
"integrityImpact": "HIGH",
"availabilityImpact": "HIGH"
},
"exploitabilityScore": 2.8,
"impactScore": 5.9
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"timestamp": "2026-06-22T19:10:34.711170Z",
"id": "CVE-2026-12050",
"options": [
{
"exploitation": "none"
},
{
"automatable": "no"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"version": "2.0.3"
}
}
]
},
"weaknesses": [
{
"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"type": "Secondary",
"description": [
{
"lang": "en",
"value": "CWE-89"
}
]
}
],
"configurations": [
{
"nodes": [
{
"operator": "OR",
"negate": false,
"cpeMatch": [
{
"vulnerable": true,
"criteria": "cpe:2.3:a:pgadmin:pgadmin_4:*:*:*:*:*:postgresql:*:*",
"versionStartIncluding": "1.0",
"versionEndExcluding": "9.16",
"matchCriteriaId": "6C00C802-CCFB-4A7B-835E-FBE61FFC87FD"
}
]
}
]
}
],
"references": [
{
"url": "https://github.com/pgadmin-org/pgadmin4/commit/3379c39865d3ab6f52afce97361fb16bcdd77cd2",
"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"tags": [
"Patch"
]
},
{
"url": "https://github.com/pgadmin-org/pgadmin4/issues/10026",
"source": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
"tags": [
"Issue Tracking",
"Patch"
]
}
]
}