Start trial

Unauthenticated SQL Injection in WordPress Core Fixed in 7.0.2

On 17 July 2026, the WordPress core team shipped WordPress 7.0.2, a security release addressing both a critical and a high severity vulnerability. The critical

PublishedJuly 17, 2026
Chazz Wolcott avatar
Chazz Wolcott
Security Researcher at Patchstack

On 17 July 2026, the WordPress core team shipped WordPress 7.0.2, a security release addressing both a critical and a high severity vulnerability. The critical issue is an unauthenticated SQL injection reachable through the REST API’s batch endpoint, via a route/handler confusion that defeats input validation. The WordPress team and the reporting researcher classify the full chain as a remote code execution.

Patchstack deployed RapidMitigate rules for these vulnerabilities immediately, and have already seen exploitation attempts in our logs.

Because the critical issue is unauthenticated and mass-exploitable, the Core team treated this as the highest priority issue, and pushed out a force update to impacted sites. However, we still recommend confirming you’re on the most recent version of your branch:

  • WordPress 7.0.2 (both issues fixed)
  • WordPress 6.9.5 (backport of both issues)
  • WordPress 6.8.6 (unaffected by the route confusion vulnerability, SQL injection patch backported)

✌️ Our users are protected from this vulnerability. Are yours?

Web developers

Mitigate vulnerabilities in real-time without changing code.

See pricing
Plugin developers

Identify vulnerabilities in your plugins and get recommendations for fixes.

Request audit
Hosting companies

Protect your users, improve server health and earn additional revenue.

Patchstack for hosts

Technical Overview

The two vulnerabilities

#TypeSeverityAffected InReported By
1Faciliated SQL Injection (WP_Query)High6.8-7.0.1TF1T, dtro, and haongo
2REST API batch route/handler confusionCritical6.9-7.0.1Adam Kues (Assetnote / Searchlight Cyber)

The SQL injection primitive (#1) reaches back to 6.8, but the batch-handler confusion that transforms it into an unauthenticated and remotely reachable attack (#2) was only introduced in 6.9.

These are best understood as one two-stage chain: a REST-layer flaw that defeats input validation, feeding a query-layer flaw that turns unvalidated input into SQL.

Vulnerability #1: Facilitated SQL injection in WP_Query

The first issue is in how WP_Query builds the SQL clause for the author__not_in query variable. In 7.0.1, the value was only sanitized when it arrived as an array:

Screenshot of an extract from the vulnerable function in 7.0.1

The is_array() gate is the flaw. If author__not_in arrives as a string, the array_map( 'absint', ... ) sanitization is skipped entirely. The raw value is then cast with (array), wrapping the string into a single element; imploded; and concatenated directly into the SQL WHERE clause. No conversion to an integer or parameterization.

It’s a facilitated SQL injection because author__not_in isn’t normally attacker-controllable. Under normal REST processing, the corresponding author_exclude parameter is validated as an array of integers and would never reach WP_Query as a string. the vulnerability only becomes exploitable when something changes this processing path to let an unvalidated value through; this is exactly what the second vulnerability provides.

The fix routes the value through wp_parse_id_list(), which converts any input into a clean list of integers before it can reach the query:

A screenshot of the patched code from 7.0.2

With this fix, sanitization no longer depends on the input’s type.

Vulnerability #2: REST API batch route/handler confusion

The critical issue is in the REST API batch endpoint, handled by WP_REST_Server::server_batch_request_v1(), which lets a client bundle several sub-requests into one call. The handler parses each sub-request, matches it to a route handler, validates it, then dispatches.

The root cause is an index desynchronization between the arrays the handler builds and the array it later reads back.

Matches are appended to a compact array; an entry is only added for sub-requests that are not errors:

Part of the vulnerable code in 7.0.1 for Vulnerability #2

But dispatch reads matches back by the request’s original index:

Part of the vulnerable code in 7.0.1 for Vulnerability #2

An attacker seeds the batch with a first sub-request whose path is http://. That fails wp_parse_url() and becomes a parse_path_failed error. It stays in $requests at index 0 but is never added to $matches. From that point on, every handler lookup is shifted by one:

Original indexSub-requestReads $matches[$i]
0invalid POST http://(error)
1POST /wp/v2/postshandler for /batch/v1
2POST /batch/v1next handler / none

The attacker nests a second batch to repeat the shift one level deeper, landing the payload so that a GET /wp/v2/posts?author_exclude=<injection> request is:

  • validated against the POST/create posts handler where author_exclude is not a registered collection filter, so the array-of-integers functionality that would normally reject a scalar never runs; and
  • executed against the shifted match for the GET collection route, invoking the unauthenticated get_items() callback.

The core security failure: after the shift, a request’s method, route, validation schema, permission callback, and final callback are no longer bound to the same handler. Validation is done by one handler, execution by another. That is what carries an unvalidated author_exclude all the way into WP_Query, where the SQL injection vulnerability can be reached.

The fix applies two changes. First, the error branch now keeps the arrays index-aligned by pushing the error into $matches as well.

Second, a re-entrancy guard was added so a fresh top-level REST cycle cannot begin while another dispatch is in flight. Internal sub-requests must go through dispatch(), not a new serve_requests().

A series of patched functions showing the fixes in 7.0.2

Together these close both the array misalignment that caused the route confusion and the nested-dispatch behavior used to reach it.

Conclusion

WordPress 7.0.2 fixes a two-stage chain: a type-confused SQL injection in WP_Query reaching back to 6.8, and (starting in 6.9) a REST batch route/handler confusion that unbinds validation from execution and feeds unvalidated input into the first injection, all without authentication. These vulnerabilities present a real threat, one Patchstack has already seen attempted in the wild, and are a strong reason to ensure your sites are either updated, or protected with RapidMitigate.

Like it? Share it.

Related articles