

A critical SQL injection vulnerability in Drupal core was publicly disclosed on 20 May 2026. If your organisation runs Drupal on PostgreSQL, this one demands immediate attention. No authentication required. No special access needed. An anonymous visitor can extract data from your database, and in the worst cases, escalate privileges or execute code remotely.
On 20 May 2026, the Drupal Security Team published advisory SA-CORE-2026-004, disclosing a SQL injection flaw in Drupal's database abstraction API. The vulnerability is tracked as CVE-2026-9082. Two days later, on 22 May 2026, the risk score was revised upward to 23 out of 25 on Drupal's own rating scale, placing it firmly in the "Highly critical" band.
The flaw sits in how Drupal's EntityQuery system constructs SQL when running on PostgreSQL. The patch was shipped across six fixed releases, and the advisory is unambiguous: if you're on a vulnerable version with PostgreSQL as your database engine, you're exposed to unauthenticated remote exploitation.
The risk score of 23/25 reflects a near-worst-case combination of attributes. Access complexity is rated None. Authentication is None. Confidentiality impact is rated All. Integrity impact is rated All. The exploit availability is documented. That last point matters enormously in practice: Tenable's analysis notes that a detection proof-of-concept and patch diff became publicly available within hours of disclosure, and that Drupal vulnerabilities of this severity have historically seen active exploitation within hours to days.
NVD assigned a CVSSv3 score of 6.5, which at first glance seems inconsistent with the urgency. Tenable explicitly acknowledges this gap, noting that Drupal's own rating better reflects the potential severity for affected configurations, precisely because the unauthenticated attack vector changes the calculus entirely.
Confidentiality and integrity both at maximum impact means an attacker can read anything the database user can access and, in some scenarios, write data or escalate to remote code execution. For a government portal, a banking application, or an enterprise intranet running on PostgreSQL, that's a breach-level event reachable from a public endpoint. Even if your Drupal instance sits behind authentication at the application layer, the injection point predates any login check. Your attack surface is every HTTP request that hits the server.
The vulnerable code lives in core/modules/pgsql/src/EntityQuery/Condition.php. That path alone tells you something: this is a PostgreSQL-specific override, not a shared code path.
Inside that file, a loop processes case-insensitive IN conditions. The loop iterates over an array of values and builds SQL placeholders using array keys as placeholder names. The assumption baked into the original code is that those keys will always be sequential integers: 0, 1, 2, and so on. That assumption holds when the caller passes a numerically-indexed array. It breaks the moment an associative array arrives.
As Searchlight Cyber's technical analysis explains, "if the caller hands the entity query an associative array, $key can be any string, and that string ends up inside the SQL." That's the injection. The key you supply becomes part of the query structure, not just a bound parameter value.
MySQL and SQLite are unaffected because they use Drupal's standard Connection::expandArguments() path, which generates sequential placeholder names from an internal counter and never reads user-supplied keys. The case-sensitivity override introduced for PostgreSQL is the sole path where key values flow into SQL construction.
Two additional files are implicated in the broader fix: core/lib/Drupal/Core/Entity/Query/Sql/Condition.php and core/lib/Drupal/Core/Entity/Query/Sql/ConditionAggregate.php. The patch itself is straightforward: array_values() is applied to reset keys to sequential integers before any SQL is emitted, closing the injection point across all three locations.
Two concrete attack vectors have been documented. Both are reachable by anonymous users with no credentials.
The first uses the JSON login endpoint at /user/login?_format=json. When Drupal's JSON login handler receives a POST body, it accepts a JSON object. If the name field is submitted as a nested JSON object rather than a plain string, Drupal's parameter handling converts it into an associative array internally. A second key within that object, carrying embedded SQL, becomes the injection point. Searchlight Cyber demonstrated a divide-by-zero gadget that turns this into a boolean-blind channel: an HTTP 500 response when a predicate evaluates true, and an HTTP 400 when it evaluates false. One bit of information per request.
The second vector uses JSON:API filter parameters. A query string like filter[t][condition][value][`]=x exploits how Drupal parses bracket-notation keys. A single backtick, quote, or structurally invalid character in the key position corrupts the placeholder name and triggers a SQLSTATE[HY093] error, confirming the injection path is active.
The speed at which blind extraction becomes practical is notable. Searchlight Cyber describes it as "one HTTP request per bit," which makes extraction of arbitrary data the database user can read achievable at scanning speeds. For a table holding user credentials, session tokens, or personal data, that rate is fast enough to matter before most monitoring tools would fire an alert, which is exactly why tracking indicators of compromise at the HTTP layer is worth building into your detection posture.
The Drupal Security Team advisory lists the following affected versions for sites running PostgreSQL:
The fixed releases are: 10.4.10, 10.5.10, 10.6.9, 11.1.10, 11.2.12, and 11.3.10.
Drupal 7 is unaffected. End-of-life branches 9.5 and 8.9 have hotfix files made available separately, per Tenable, though running EOL software carries its own risks that a single hotfix doesn't resolve. Sites on MySQL, MariaDB, or SQLite are not affected by CVE-2026-9082 specifically, but read the next section before deciding to defer the update entirely.
If you're running PostgreSQL, patch today. Not this week. Today. The proof-of-concept is already public, the exploitation mechanics are documented, and the historical pattern with high-severity Drupal vulnerabilities is that active exploitation follows disclosure within days. Update to the fixed release matching your current branch.
If you're running MySQL, MariaDB, or SQLite, you're not exposed to CVE-2026-9082. You should still update. The releases carrying these patches also include coordinated Symfony and Twig security fixes. Those fixes address separate issues in dependencies that many Drupal sites share, and bundling them into a single release is standard Drupal security practice. Skipping the update because you don't run PostgreSQL leaves those dependency issues unaddressed.
On the monitoring side, look for anomalous HTTP 500 and HTTP 400 response patterns on /user/login with a _format=json parameter, particularly in high-frequency sequences from a single source IP. The boolean-blind extraction technique generates a distinctive alternating pattern of 500 and 400 responses. Unusual bracket-notation keys in JSON:API filter parameters are equally worth flagging. If your WAF or SIEM doesn't currently inspect JSON:API query strings at this level of detail, now is the time to close that gap. For a structured approach to building that kind of detection capability, cyber threat intelligence frameworks provide a useful starting point.
As of the initial disclosure, the Drupal Security Team and Tenable both reported no confirmed exploitation in the wild. That status will not hold indefinitely. The window between "no observed exploitation" and "active scanning" for vulnerabilities at this severity level is measured in hours, not weeks.
You're not vulnerable to CVE-2026-9082. The injection exists exclusively in the PostgreSQL-specific entity query condition handler. MySQL and MariaDB use a different placeholder-generation path that never incorporates user-supplied array keys into SQL. That said, update anyway, the same release trains include Symfony and Twig security fixes that apply regardless of your database engine.
A detection proof-of-concept and the patch diff were publicly available within hours of the 20 May 2026 disclosure, according to Tenable's analysis. A full weaponised exploit has not been confirmed in public repositories at the time of writing, but the technical detail in Searchlight Cyber's write-up is sufficient for a competent attacker to construct one. Treat exploitation as imminent rather than theoretical.
Drupal 7 is not affected by this vulnerability. The EntityQuery condition handling involved does not exist in that codebase. However, Drupal 7 reached end of life in January 2025, and running it carries a separate and growing set of unpatched risks that no single advisory exemption changes.
Check the version string in your Drupal admin status report at /admin/reports/status, or run drush status from the command line. You're looking for 10.4.10, 10.5.10, 10.6.9, 11.1.10, 11.2.12, or 11.3.10 depending on your branch. You can also verify the fix directly by inspecting core/modules/pgsql/src/EntityQuery/Condition.php and confirming the presence of an array_values() call applied to the values array before placeholder generation. If it's absent, you're still running the vulnerable version.