What breaks and who should care
If your monitoring tool just raised CVE-2025-1094, the thing that is broken is the way PostgreSQL’s client library (libpq) and a few command‑line tools handle quoted strings. The bug can let an attacker inject arbitrary SQL when the output of certain escaping functions is later fed to the psql console, or when a specially crafted argument reaches a utility while the server is using a BIG5 client encoding and an EUC_TW or MULE_INTERNAL server encoding.
We keep a daily-updated list of vulnerabilities CISA has confirmed as actively exploited, including remediation deadlines.
Anyone who runs PostgreSQL in production, especially those who let applications build command‑line calls to psql from user data, needs to pay attention. The CVSS score is 8.1, which puts it solidly in the high severity bucket. That means the potential impact is significant – an attacker could gain the same privileges as the database user that runs the vulnerable command.
How the bug works
The vulnerability lives in four libpq helper functions: PQescapeLiteral(), PQescapeIdentifier(), PQescapeString() and PQescapeStringConn(). Their job is to take a piece of text and return a safely quoted version that can be concatenated into an SQL statement. In most code they work fine, but the NVD description points out a subtle flaw: the quoting logic does not correctly neutralise every possible quoting syntax.
In practice this means that under certain circumstances an attacker can craft input that, after being passed through one of those functions, still contains a token that the PostgreSQL parser will treat as code rather than data. The trick only becomes exploitable when the escaped string is handed to psql – for example, an application builds a shell command like psql -c "SELECT …" using the escaped value. psql then interprets the string again, and the hidden token is executed as SQL.
A second attack surface is the command‑line utilities themselves. When the client encoding is set to BIG5 and the server encoding is one of EUC_TW or MULE_INTERNAL, the utilities mishandle quoting in their own argument parsing. An attacker who can influence a command‑line argument (for instance, a wrapper script that forwards user input to pg_dump) can cause the same kind of injection.
Both paths rely on a combination of improper quoting and a specific character‑set configuration. If you never feed escaped strings into psql, or you always run the server with UTF‑8 on both sides, the risk drops dramatically. Still, the bug is real and the CVSS rating reflects the worst‑case scenario.
Assessing your exposure
First, find out whether you are running a version that is vulnerable. The NVD does not publish a simple list of version numbers, but it does say that any release prior to the patched release for each supported line is affected. The table below (automatically inserted by the platform) shows exactly which releases are safe and which are not. Your job is to compare the version you have installed with that table.
Run one of these commands on the host that runs PostgreSQL:
psql --version– prints the server version.pg_config --libpq-version– prints the libpq version.
If the version you see appears in the “affected” column of the table, you are vulnerable.
Next, check whether you are using the risky encoding combination. Connect to the database and run:
SHOW client_encoding;SHOW server_encoding;
If the client side reports BIG5 and the server side reports either EUC_TW or MULE_INTERNAL, you are in the dangerous configuration space.
Finally, audit your application code for any place that does the following:
- Calls any of the four libpq escape functions and then concatenates the result into a shell command that invokes
psqlor another PostgreSQL utility. - Builds a command‑line argument for a PostgreSQL tool from user‑supplied data.
If you find such patterns, you are at real risk of exploitation.
Mitigation and remediation
The cleanest fix is to upgrade to the patched release for your PostgreSQL branch. The table below lists the first safe release for each line. Upgrade the server, the libpq library and any client tools that ship with the distribution. After the upgrade, restart the service so the new binaries are loaded.
If you cannot upgrade immediately, you have a few short‑term options:
- Force both client and server encodings to UTF‑8. This removes the special‑case handling that triggers the second attack vector.
- Avoid feeding escaped strings into
psql. Instead, use a proper database driver that sends the query over the wire, or use parameterised queries inside the client library. - Sanitise any command‑line arguments that come from outside sources. Strip or reject characters that could be interpreted as quoting syntax (single quotes, backslashes, etc.) before they reach the utility.
For applications that already use prepared statements or an ORM, the risk is already low – those layers never invoke the vulnerable escape functions directly. The main focus should be on legacy scripts that stitch together psql calls.
After you have applied a fix, verify it by re‑running the version check and confirming that the reported version now appears in the “fixed” column of the table. Also, re‑run the encoding queries to ensure you are no longer on the BIG5/EUC_TW or MULE_INTERNAL combo.
When a patch isn’t available
In the rare case that you are locked to an older release that has no patched binary, you can mitigate by isolating the vulnerable component. Run the database behind a firewall that only allows trusted hosts to connect. Disable any scripts that invoke psql with user data. If you must keep the encoding configuration for legacy reasons, wrap the utility calls in a small wrapper that validates the arguments against a whitelist of safe characters.
Another defensive measure is to enable PostgreSQL’s log_statement = 'all' temporarily, so you can see if any unexpected SQL is being executed. Watch the logs for statements that contain literal quoting patterns you did not intend.
Finally, consider moving the workload to a container or VM that you can patch more quickly. A short‑lived environment that can be rebuilt from a newer base image eliminates the need to back‑port patches.
What to do next
1. Identify the version you are running – psql --version and pg_config --libpq-version.
2. Compare it with the table below.
3. Check the client and server encodings – SHOW client_encoding; and SHOW server_encoding;.
4. Search your code for the four libpq functions and any shell‑invoked psql calls.
5. If you are on an affected release, upgrade to the patched release for your branch.
6. If you cannot upgrade, switch both encodings to UTF‑8 and stop feeding escaped strings to psql.
7. Test the changes, confirm the version now appears in the “fixed” column, and monitor logs for anomalies.
That’s the whole story. The vulnerability is real, the impact can be severe, but the fix is straightforward – upgrade, or at the very least change your encoding and stop using the risky pattern. Keep the table below handy, and you’ll know exactly where you stand.
Affected versions
NVD has not published machine-readable version ranges for CVE-2025-1094 yet. Check the vendor advisory for the exact affected and fixed releases before you plan an upgrade.


