Vulnerability Research

Emergency WordPress 6.8–7.0 Updates: Both CVEs Are in KEV, and Public wp2shell Evidence Reaches SQLi

Upgrade WordPress 6.8.0–6.8.5 to 6.8.6, 6.9.0–6.9.4 to 6.9.5, and 7.0.0–7.0.1 to 7.0.2; both CVEs are in KEV, with CVE-2026-63030 overdue since July 24 and CVE-2026-60137 due August 4; current #16658 positives prove only route confusion, the pinned historical template supports the SQLi front half, and the full RCE tail lacks independent reproduction; close only with version, artifact, and runtime evidence.

On beige paper, a sealed envelope splits into two mechanical lines: an upper line passes a key and a locked door with a cloud-shaped side tube, while a lower line passes a blue booklet, integer beads, a stone arch, and a cylinder before both lines end in gray fog.
In this article

Research basisReview of WordPress release notices, repository advisories, pinned repair commits, CNA and CISA ADP records for both CVEs, CISA KEV raw catalog 2026.07.24, coordinated Searchlight and Cloudflare disclosures, both generations of the public ProjectDiscovery detector and their validation, false-negative, and replacement records, the pinned July 18 public implementation, and BleepingComputer's attributed watchTowr observation report

SourceWordPress 7.0.2 release notice / WordPress repository GHSAs and pinned repair commits / CNA and CISA ADP records for both CVEs / CISA KEV raw catalog 2026.07.24 / Searchlight Cyber wp2shell disclosure / Cloudflare coordinated defense account / ProjectDiscovery historical PR #16596 and pinned 9e6cb91 template, issue #16629, replacement PR #16658, and pinned d51e9a3 current template / pinned July 18 public implementation / BleepingComputer attributed watchTowr observation report / SOSEC source review

1 Update the maintenance branch before debating wp2shell

The remediation decision fits in the first ticket: update WordPress 6.8.0–6.8.5 to 6.8.6, 6.9.0–6.9.4 to 6.9.5, and 7.0.0–7.0.1 to 7.0.2. WordPress places the 6.8 line only inside the official range for CVE-2026-60137. The 6.9 and 7.0 lines fall inside both CVE-2026-60137 and CVE-2026-63030, and those are the two lines for which WordPress states the combined remote-code-execution result. CISA added both CVEs to KEV on July 21: CVE-2026-63030 carries a July 24 due date that had passed when this report was updated, and CVE-2026-60137 carries an August 4 due date. An affected site needs the complete fixed maintenance release or a vendor-equivalent build with an auditable backport identity.

WordPress shipped all three fixed lines on July 17, 2026, and enabled a forced automatic update for affected versions. "Enabled" describes an action taken by the update service. Asset owners still need per-site evidence that the package downloaded, reached disk, replaced every request-serving process, and updated rollback sources. Organizations subject to CISA requirements should treat the missed July 24 date as a trigger for immediate rollout, a recorded overdue exception, and investigation of the exposure window. Other organizations should also treat KEV as an external known-exploitation priority signal. For WordPress 7.1 test assets, beta 2 is the specifically documented fixed prerelease; production closure should use a maintained formal release. Releases before 6.8 sit outside these two advisory ranges, while their support status and exposure to other vulnerabilities remain a separate lifecycle problem.

KEV currently answers one question: both vulnerabilities have known exploitation. Both CISA ADPs changed SSVC exploitation to active on July 21: CVE-2026-60137 records Automatable=no and Technical Impact=total, while CVE-2026-63030 records Automatable=yes and Technical Impact=total. The July 17 none values remain only as the historical state before that turn. Public technical reproducibility stays in a separate field: the pinned historical detector supports unauthenticated time-based blind-SQL-injection reachability, the current detector observes route-confusion behavior only, and the public record supplies no replay transcript spanning SQL injection, persistence, and RCE. Version, artifact, and runtime acceptance close remediation; the two detector generations support different investigative levels.

2 How one anonymous request reaches the SQL boundary

The front half can be explained in six plain steps before returning to source details. The pinned historical PR #16596 template and fixed source jointly reach the SQL-injection boundary at step six. The current #16658 detector stops earlier at route-confusion behavior and sends no SQL condition or timing probe. WordPress supplies the official conclusion that the two CVEs combine to remote code execution; the database-to-code-execution mechanism beyond step six lacks an independently verified complete implementation in the record used here.

  1. The batch endpoint accepts ordered subrequests. An anonymous client places multiple REST operations into /batch/v1. The server retains the original request sequence, route-match state, and validation state. Later processing uses a shared positional index to join those three views of each member.

  2. One preparation error leaves the state sequences at different lengths. In affected serve_batch_request_v1(), an early WP_Error enters only $validation; the corresponding $matches position is absent. From that point forward, the same numeric index can retrieve state belonging to different original subrequests.

  3. A nested subrequest reopens a top-level serving lifecycle. The batch is already running inside dispatch(), yet affected integration and server entries can enter top-level serving behavior again. The internal item crosses the dispatch context that owns it, adding a second conflict among route matching, parameter registration, and later members.

  4. A public parameter reaches the posts controller's query context. The historical ProjectDiscovery PR #16596 layout places a categories request carrying author_exclude inside the nested batch and uses the preceding state conflicts to deliver that value under the posts controller. Pinned WordPress 7.0.1 source shows the posts controller mapping public author_exclude to internal author__not_in at lines 239–270.

  5. The query layer lets a scalar avoid per-member integer conversion. A cache-key cleanup introduced with WordPress 6.8 normalized arrays only. A scalar retains its original text until a late cast wraps it in a one-element array for joining. The late container change cannot recover the element conversion that the scalar already skipped.

  6. The historical public detector observes a blind-SQL condition at this point. The pinned PR #16596 template uses structurally equivalent false- and true-condition requests and requires HTTP 207, a specific error marker, and a true-case duration of at least seven seconds. A complete positive flow supports unauthenticated time-based blind-SQL-injection reachability. The template extracts no data and performs no later code execution. Multiple false-negative reports filed on July 22 state that the third SQLi request does not execute under some conditions, so a historical non-match records one unsatisfied flow. ProjectDiscovery replaced this flow with the route-confusion template on July 24.

The same sequence explains the version split. The query-shape regression first shipped in 6.8.0, so 6.8.0–6.8.5 need the CVE-2026-60137 repair on their own. The relevant REST batch change first shipped in 6.9.0, and the official ranges begin overlapping there. The fixed 6.8.6 tree carries two extra REST changes in a grouped backport, showing that maintainers moved the code into that line. WordPress still excludes 6.8 from the published CVE-2026-63030 range. Source state and advisory scope answer separate operational questions and should be recorded separately.

2.1 Position arrays and the service lifecycle preserve request identity

The batch index is a relationship key. A later loop traverses original requests and uses $i to read $matches[$i] and $validation[$i]. An internal request that failed during preparation still needs a position in both sequences. Once one position disappears, the ith route match and ith validation result can describe different requests. Fixed code stores the same error object in both sequences. It preserves response cardinality and keeps every error, null placeholder, or ordinary result attached to the member that produced it.

The require-all-validate behavior supplies an ordinary control. When a batch requests complete validation and an error occurs, WordPress returns an error or null for each position and keeps later members in place. Acceptance should therefore observe response count and positional ownership. Rejecting every batch that contains an error could hide the alignment defect while breaking valid protocol behavior. A crash-free request records runtime survival; positional comparison separately establishes whether request, match, and validation state stayed associated.

The dispatch guards protect ownership at another scale. rest_api_loaded() is WordPress's outer REST integration entry, serve_request() is the server's serving entry, and dispatch() handles a request object inside active matching and validation state. The fixed release checks is_dispatching() at the first two entries. During an active internal dispatch, the integration function stops early and the server method returns false. A legitimate subrequest stays in its current dispatch, and top-level constants, initialization, response output, and termination behavior retain their original single lifecycle.

On beige paper, an envelope releases four blank request cards through a central dispatcher into two wooden racks. The left rack has four upper slots with an orange error card in the third and a missing corresponding position below; the right rack has four slots in both rows with its orange positions vertically aligned. Below, a blue inner loop remains inside a blue outer loop and is constrained by a green reentry gate.
Figure 1. The fixed release keeps an error in the same match and validation position and keeps an internal subrequest inside its existing dispatch() cycle; the two repairs preserve the identity of one request at two scales.

2.2 The query repair sends every processed shape through one integer list

CVE-2026-60137 came from a change with a legitimate cache goal. WordPress changeset 59766, represented by Git commit c22e267ccae50b45e9ae6e4b1e55ce68c408f842, entered trunk in February 2025 and first shipped in 6.8.0. For an array-shaped author__not_in value, it removed duplicates, applied absint to each member, sorted the list, and wrote normalized state back so semantically equivalent inputs could share stable cache semantics. A scalar bypassed the is_array() branch. Only when implode() was about to join the list did (array) wrap the scalar, leaving the member's original text unchanged.

WordPress 6.7.2 is an effective historical control. Its older sequence casts to an array first and then applies an absolute-integer conversion to each member, giving scalar and array forms the same element treatment. WordPress 6.8.0 contains the shape-dependent branch, and commit ancestry agrees with the advisory's lower boundary. The neighboring author__in path also continued converting each member across input shapes. Together those comparisons locate the broken property in author__not_in handling. The source documentation calls the argument int[]; the general runtime entry demonstrably processes a scalar as well, so the boundary nearest SQL has to constrain every runtime shape it accepts and uses.

The fixed implementation retains the outer ! empty() gate and sends strings or arrays that enter the branch through wp_parse_id_list(). Strings split on commas or whitespace, array input retains scalar members, each retained member passes through absint, and duplicates are removed. WP_Query continues only when the parsed list is nonempty. It then sorts the identifiers, builds the author-exclusion condition from integers, and writes back the normalized query state. When parsing produces an empty list, the clause and its associated writeback are absent.

There are two empty paths. An empty string, string zero, integer zero, or an empty array ends at the outer gate and never calls the parser. A whitespace-only string or a nonempty array containing no retained scalar members can enter the branch and then parse empty. Fixed WordPress preserves compatibility-oriented conversion: an ordinary nonnumeric scalar can become integer zero, and a negative value becomes a nonnegative integer. Acceptance should establish that original nonnumeric text no longer survives into query state or SQL-list syntax, equivalent lists converge, and legitimate author filtering still behaves as intended. Requiring every malformed value to return a request error would test a contract the fixed implementation does not promise.

On beige paper, an empty outer basket stops before a closed gate; beyond it, one scalar bar and a four-token tray enter the same sieve, a parsed-empty basket stops on a side path, and the four tokens pass a sorting rack and green SQL gate in sequence; after the gate, a separate junction sends a blue line back to a ledger while the main line continues to a cylinder, and an empty rust-colored bypass above is visibly broken.
Figure 2. The old late (array) cast changed the container only; fixed WordPress sends strings and arrays through wp_parse_id_list() and allows only a parsed-nonempty integer list into the query condition.

3 Record known exploitation, official RCE, public SQLi, and the unverified tail separately

3.1 The historical template pins SQLi; the current template reports route confusion

The WordPress repository advisory makes a clear product statement for 6.9.0–6.9.4 and 7.0.0–7.0.1: the REST API batch route confusion in CVE-2026-63030 combines with the author__not_in SQL injection in CVE-2026-60137 to produce remote code execution. The maintainer advisory establishes the product outcome; pinned fixed source establishes the three restored program properties. Together, those evidence classes determine update priority and the acceptance target.

Searchlight Cyber named its result wp2shell and reported pre-authentication triggering on a stock, plugin-free WordPress installation with no other preconditions, while withholding the technical details during the update window. Cloudflare's coordinated account limits the anonymous path it describes to WordPress 6.9 or later without a persistent object cache. WordPress's default object cache is request-local unless a site installs a persistent implementation, so a stock plugin-free installation normally fits that Cloudflare environment description. Cache state helps an investigator interpret attributed disclosure conditions. Official version scope continues to decide remediation.

On July 18, ProjectDiscovery merged PR #16596. The historical template pinned at 9e6cb912c9d4df492b68ac0ecf8c333e2357de06 references both CVEs and records validation against vulnerable and fixed targets. It fingerprints WordPress and sends structurally equivalent false- and true-condition groups to POST /?rest_route=/batch/v1. The false-condition step requires HTTP 207 and parse_path_failed; the true-condition step additionally requires JSON and a response duration of at least seven seconds. The template sets no maximum duration for the false condition and calculates no duration delta. Its positive evidence level is a contributor-validated unauthenticated time-based blind-SQL-injection detector. SOSEC did not rerun this historical template, so upstream validation remains attributed to ProjectDiscovery and the contributor.

On July 22, a contributor reported multiple false negatives in PR #16596 and issue #16629 and described conditions under which the third SQLi request never executes. On July 24, ProjectDiscovery used PR #16658 head 5d14aeb15ba2ba90ebcffa97723b63150658a97d to replace the timing/SLEEP SQLi flow with a deterministic route-confusion probe. The contributor reported expected results in a development environment and on the live targets that had produced the false negatives, and issue #16629 closed as completed with the replacement. The main state pinned for this report is d51e9a38ae587ccdf7a75fe6aa0e11c81e7d7972, where the template contains a two-request flow.

The current template first uses WordPress markers in a GET response as an internal gate, then sends one batch POST with no SQL parameter. A positive result requires HTTP 207, JSON, block_cannot_read, and absence of the fixed-routing marker rest_term_invalid; its metadata states that the probe executes no SQL and uses no timing oracle. A current positive supports route-confusion behavior under that layout. A current negative records one run in which the fingerprint, request execution, and four matchers did not all align. The historical three-request positive supports SQL-injection reachability, while the historical negative carries the separate issue #16629 false-negative limit. Preserve different records for each generation: author_exclude, three responses, durations, and third-request execution for the historical template; the GET gate, batch response, and four matcher outcomes for the current template. Data extraction, unintended code execution, and compromise require their own evidence.

3.2 The public tail implementation remains a code claim

Public commit 98716c82d2fe9b84ff15e5f6e7aa90d30927d602 describes a later implementation that uses timing observations to recover values, reuses WordPress state, attempts administrator creation, and then attempts plugin upload and activation. The pinned file is specific enough to review the intended functions and control flow. The repository supplies no successful transcript or CI result, SOSEC did not run the implementation, and the adopted record contains no independent reproduction. Its current evidence level is a concrete, reviewable, unverified tail implementation. It cannot serve as a production indicator or as an independent successful reconstruction of complete wp2shell.

Remediation remains urgent. CISA lists both vulnerabilities as known exploited, the product maintainer supplies the combined RCE finding, the historical ProjectDiscovery positive reaches unauthenticated blind SQL injection, and the current flow supplies a narrower route-confusion signal. Defenders first establish which official interval contains an asset and then install the fixed release for that branch; a non-match from either detector generation remains unresolved. Incident responders keep a precise ladder: an edge request can establish scanning or an attempt; a current-template positive can establish route-confusion behavior; a complete historical timing flow can establish SQL-injection reachability; reliable evidence that the server executed unintended code establishes RCE; unauthorized data access, execution, or control establishes compromise. Every step is assigned from observed records.

CISA's state made a clear turn over four days. The SSVC containers for both CVEs recorded exploitation as none at their respective late-July-17 timestamps; those values now serve only as the historical analysis before the turn. On July 18, BleepingComputer relayed Benjamin Harris and watchTowr's statement that the team was seeing "first signs." The report supplied no telemetry, IOC, victim, request classification, or successful result, leaving that observation unclassified. On July 21, CISA added both CVEs to the raw KEV catalog. The updated ADP for 60137 records Exploitation=active, Automatable=no, and Technical Impact=total; the 63030 ADP records Exploitation=active, Automatable=yes, and Technical Impact=total. This report uses KEV raw catalog version 2026.07.24, released at 2026-07-24T17:40:56.0086Z. The current defense state is "both known exploited"; CISA due dates are July 24 for 63030 and August 4 for 60137.

The KEV entries and both active ADPs establish known exploitation and a government remediation date for each CVE. Public technical reproducibility remains a separate record: no public, successful, replayable transcript currently spans SQL injection, persistence, and RCE, and the adopted sources do not identify which layer the events supporting KEV reached. Asset remediation proceeds immediately from KEV and official version scope. A specific incident still requires its own classification among scanning, route confusion, SQL-injection reachability, RCE, and compromise.

4 The repair must pass both code-property and runtime acceptance

4.1 The maintenance line decides which properties to test

WordPress 6.8 acceptance is query-specific. In an isolated environment, compare a production-equivalent 6.8.5 artifact with 6.8.6 using ordinary integer arrays, numeric scalars, a nonnumeric placeholder, duplicate members, and reordered lists. The fixed artifact should converge on integer semantics; original nonnumeric text should disappear from query state and SQL-list syntax; valid author filtering should retain its business result; and both outer-empty and parsed-empty paths should omit the exclusion condition and corresponding writeback. The two additional REST changes present in 6.8.6 are fixed-tree facts; the acceptance record follows the advisory and assigns 6.8 only to CVE-2026-60137.

WordPress 6.9 and 7.0 also need batch-position and dispatch-ownership controls. An in-process fixture can place a preparation error before distinguishable valid members. A fixed build should retain the original response cardinality and keep each error, null placeholder, and valid result in its own position. A white-box harness may additionally compare $matches and $validation indexes for each item. A separate lifecycle control invokes the integration and server entries while an internal dispatch is active; the fixed build should stop at the two new guards, while a paired idle-dispatch control should preserve ordinary top-level service behavior.

The historical template pinned at 9e6cb912c9d4df492b68ac0ecf8c333e2357de06 belongs only in an isolated, explicitly authorized SQLi front-half comparison. An affected 6.9.4 or 7.0.1 baseline is expected to match the complete three-request flow, while 6.9.5 or 7.0.2 is expected not to match. A positive supports time-based blind-SQL-injection reachability under the tested layout. The July 22 false-negative record limits a historical negative: after preserving all three request and response groups, both condition durations, evidence that the third request executed, target artifact, Nuclei and template versions, template digest, operator, time, and network conditions, the negative still records one unmatched run.

The current template should be pinned separately at d51e9a38ae587ccdf7a75fe6aa0e11c81e7d7972 for a route-confusion comparison. An affected baseline is expected to pass the WordPress GET gate and produce HTTP 207, JSON, block_cannot_read, and no rest_term_invalid in the batch POST; the fixed baseline is expected not to satisfy the complete matcher set. A current positive supports route-confusion behavior only, and a current negative records one unmatched run. The SQLi level still requires a historical-template positive or other direct evidence. Preserve the complete GET and POST responses, all four matcher outcomes, target artifact, Nuclei and template ref, operator, time, and network conditions. SOSEC has not executed the local regressions or either detector generation, so both acceptance designs remain "not executed." Every external asset requires explicit authorization before testing.

A passing code-property test describes the artifact under test. Production closure also requires that the same artifact reach every serving unit and that affected replicas, scaling templates, recovery images, and rollback sources leave the deployable set. A current-template positive enters route-confusion investigation; a historical-template positive enters SQLi investigation. Both negatives retain template identity and runtime conditions and stop at one unmatched run. Official version records establish scope, while fixed artifacts and runtime acceptance establish remediation. Version identity, repaired code properties, deployment coverage, and the two detector generations belong in separate fields that meet on the same asset row.

4.2 The complete release, serving units, and rollback sources need one identity

The three maintenance lines deliver the repair cluster through different version-control objects. WordPress 7.0 has three separate branch backports; 6.9 and 6.8 use grouped backports; each fixed tag has its own independent tip. A site operator should acquire the complete maintained release. A downstream distributor that rewrites commit identities needs to supply its base line, a mapping from upstream repairs into local source, immutable build identity, regression evidence, and support path. Copying one visible line from a newer branch loses companion repairs, branch context, and a durable release provenance.

The asset record should separate source or tag identity, acquired package or image, deployment identifier, and running instance. The administration-page version string supports initial location; runtime evidence identifies the code actually loaded by each process. An immutable-image service enumerates active replicas and image digests. A traditional PHP or PHP-FPM service first establishes release-switch behavior, worker lifetime, preloading, and OPcache timestamp policy, then performs only the invalidation, reload, or restart the actual mechanism requires. The pass condition is that every unit capable of accepting a request is tied to a fixed artifact and no affected or unknown unit remains in rotation.

"Cache" covers at least three separate objects in this response. The WordPress object cache stores application objects and query results. PHP OPcache stores compiled program code and can interact with preloading. A CDN stores edge responses. Each layer is handled separately, and a purge result applies only to that layer. Object-cache state helps interpret Cloudflare's attributed condition; OPcache policy helps determine when a replaced file becomes active; an edge purge supports content delivery. Vulnerability closure depends on a fixed core artifact running in the actual service units.

Rollout can move from an isolated copy into a canary and then the remaining pools. Bind each wave to the same digest or immutable image, and record planned and actual instances, start and end times, business regression, REST behavior, query results, application errors, rollback target, and approver. A failed wave stops expansion and keeps a previously accepted fixed build as the rollback destination. If an old image has evidentiary value, isolate it and mark it non-deployable. Updating autoscaling, disaster recovery, snapshots, and provider restore sources extends the fixed release into the next scale-out or recovery event.

On beige paper, an evidence bag, a sealed envelope and ledger, gears and a spool, database cylinders and a glass vial, and a node diagram with a wheel stand in a row; colored cables converge on an orange document tray while a hand inspects a junction with a magnifying glass.
Figure 3. Upgrade evidence moves from a branch target into a trusted artifact and serving instances while incident material is preserved beside it; a temporary edge control has its own start and stop times, and the core update carries final closure.

5 Close with one finite, reversible ledger

5.1 First hour, rollout, investigation, and retirement share one asset row

The site ledger should be the single authoritative working surface. It orders the first-hour scope decision, temporary control, artifact rollout, runtime acceptance, incident review, exception, and final retirement while retaining two separate conclusions: whether the known software condition has left production, and whether defined evidence sources support exploitation or compromise. An automatic-update notice, WAF dashboard, administration page, or screenshot from one node can become an attachment. No attachment advances the asset to "closed" on its own.

StageRequired recordPass conditionFailure or exceptionRetirement or closure
Scope and preservation Site, canonical hostname, line, version, provider build, exposure, cache state, serving units, owner, applicable KEV due date, and overdue state; source, window, timezone, export time, and digest for existing edge, deployment, administrator, and host records Every asset is explicitly affected, fixed, outside the official ranges, or awaiting identity; applicable CISA and internal dates have accountable owners; raw material retains a read-only origin and analyst copies remain separate Unknown versions enter an hours-scale verification queue; an asset past its applicable due date records approver, cause, and a new completion time and begins exposure-window investigation; absent telemetry stays recorded as absent Scope changes only when version and build evidence appears; failure to locate a familiar string never removes an asset automatically
Temporary exposure reduction Enforcement layer, the two batch-route forms as that layer represents them, anonymous and authenticated behavior, business effect, rule identity, owner, start time, and expiry Anonymous requests are restricted at the intended enforcement point for 6.9 or 7.0 assets that cannot update immediately; approved legitimate behavior works and an upstream correlation shows the rule actually acts before WordPress Rewrite, encoding, route changes, WAF failure, or business outage escalates the plan; an exception is reviewed daily and never renamed fixed After every serving unit is fixed and canary regression passes, remove the rule through a distinct change and retain its end time
Artifact and rollout Branch destination, source, digest or signature, image or deployment identity, wave, instances, health result, KEV date, overdue exception, fixed rollback target, and approver A trusted artifact advances through isolated, canary, and full serving pools with each result tied to specific instances A failing wave stops expansion while compatibility or configuration is investigated; rollback targets only a known fixed build Affected packages, images, snapshots, autoscaling templates, and restore sources leave the deployable set
Runtime and code acceptance Actual artifact for every serving unit; 6.8 query controls; 6.9/7.0 query, position, and dispatch controls; historical 9e6cb91 requests, durations, third-request state, and issue #16629 limit; current d51e9a3 GET/POST and four matchers; environment, raw result, and reviewer Every serving unit loads fixed code, and branch properties and ordinary business behavior pass; a current positive is labeled route confusion, a historical positive SQLi, and both negatives remain supplemental A code or business-control failure establishes failed acceptance; a current positive starts route-confusion review and a historical positive starts SQLi review; a negative leaves version and artifact state unchanged The remediation track can be signed when runtime, rollback, and acceptance records are complete together
Incident investigation Current KEV state; the 60137 active/no/total and 63030 active/yes/total ADPs; request, database, file, process, network, and identity coverage; correlation keys, baselines, authorized changes, window, and current scan, route-confusion, SQLi, RCE, or compromise level Every anomaly is compared with neighboring evidence, normal deployment, or administrator activity; KEV governs the general exploitation state, asset evidence governs the event's chain level, and conclusions state their data and time boundaries Reliable unintended execution or unauthorized access triggers the existing isolation, preservation, credential, and expanded-correlation process; files, accounts, and database objects enter the record only from observed facts Investigation may continue after remediation; final language states which conclusions the defined data supported or did not support in the defined window
Sign-off and retrospective Temporary-rule interval, KEV due-date completion or overdue explanation, open exceptions, remediation and investigation dispositions, asset owner, security reviewer, and evidence retention location and duration A new reviewer can reconstruct scope, artifact, instances, controls, investigation, and decisions without contacting the original responder Any cell that depends on chat memory, an unscoped screenshot, or a provider's oral assurance remains open The two tracks receive separate signatures; new verified tail evidence or new field evidence reopens the conclusion it affects

5.2 Remediation and compromise investigation close separately

The remediation track closes when the correct fixed line is established, a trusted artifact covers every request-serving unit, branch-applicable code properties and business behavior pass acceptance, affected content cannot return through rollback, scaling, or recovery, and temporary rules have been retired through a recorded change. Falling scan volume, zero WAF matches, a new version on an administration page, or one negative from either detector generation is a partial observation. Issue #16629 records false negatives in the historical three-request template and closed when PR #16658 supplied the route-confusion replacement on July 24. That change repairs the upstream detection workflow; each site still needs version, artifact, and runtime acceptance. A provider-equivalent backport can close the software track when its source and build identity are auditable.

The incident track closes against its own available data. KEV and both active ADPs support the general finding that both CVEs have known exploitation. Edge access and a WAF action support scanning or an attempt on a specific asset. A current #16658 positive supports route-confusion behavior under its request layout. A complete historical #16596 positive supports blind-SQL-injection reachability. Actual unintended execution on the server supports RCE. Unauthorized data access, execution, or control supports compromise. Both detector negatives stop at one unmatched run; the historical negative also carries its recorded false-negative boundary. The exposure window remains unchanged after either negative. Closure language should name the template generation, reviewed sources, time window, and missing coverage.

The three July 17 WordPress repairs restore three plain rules: an errored subrequest keeps its position in parallel state, an internal subrequest stays inside the dispatch cycle that owns it, and a value entering the author-exclusion SQL list first becomes an integer. WordPress 6.8.6 needs the third property accepted; 6.9.5 and 7.0.2 need all three. The 60137 active/no/total and 63030 active/yes/total ADPs, together with KEV, set current exploitation status and response dates; the WordPress combined RCE finding sets the product consequence; a current #16658 positive sets the route-confusion level; a historical #16596 positive sets the public SQLi front half; issue #16629 limits only the historical negative; and the unverified tail bounds incident conclusions. The resulting actions are deadline or overdue update, serving-artifact verification, generation-specific investigative escalation, unresolved status for both negative types, and finite closure for a specific incident.

Research record

6Evidence, objects, and sources

The material below preserves the identifiers and references used in this report.

6.1Research objects

Products, actors, techniques, affected objects, and control points discussed in the report.

Affected releasesWordPress 6.8.0–6.8.5

Official scope for CVE-2026-60137 only; the first fixed release is 6.8.6.

Affected releasesWordPress 6.9.0–6.9.4

Official overlapping scope for both CVEs; the first fixed release is 6.9.5.

Affected releasesWordPress 7.0.0–7.0.1

Official overlapping scope for both CVEs; the first fixed release is 7.0.2.

Query repair propertyOuter nonempty gate + wp_parse_id_list() + parsed-nonempty gate

PHP-empty values skip the branch; strings or arrays that enter it are normalized to integers, and only a parsed-nonempty list reaches the query condition.

REST repair propertySlot alignment + dispatch reentry guard

Error items keep the same position in both state arrays, and an active dispatch rejects a new top-level serving cycle.

Batch route forms/wp-json/batch/v1 | ?rest_route=/batch/v1

Searchlight names both forms as temporary WAF targets; historical #16596 and current #16658 both send their detector POST to /?rest_route=/batch/v1 .

Historical SQLi detector input9e6cb91: /wp/v2/categories?author_exclude=… → author__not_in

The historical three-request template uses the positional conflict to carry the public REST parameter into the posts-controller query mapping.

Historical SQLi detector positiveHTTP 207 + parse_path_failed | HTTP 207 + JSON + duration ≥ 7s

The complete flow supports blind-SQL-injection reachability under the tested layout; it calculates no control-versus-true duration difference, and its evidence ceiling is SQL-injection reachability.

Historical SQLi detector transitionJul 22 issue #16629 → Jul 24 PR #16658

The report states that the third SQLi request does not execute under some conditions; the issue closed as completed with the route-confusion replacement, and a historical negative records one unmatched run.

Current route-confusion detectord51e9a3: HTTP 207 + JSON + block_cannot_read + !rest_term_invalid

The two-request flow fingerprints WordPress and sends a batch probe with no SQL and no timing; a positive reaches route-confusion behavior only.

CISA KEV statusBoth CVEs added Jul 21, 2026

CVE-2026-63030 is due Jul 24, 2026, CVE-2026-60137 is due Aug 4, 2026, and this report binds catalogVersion 2026.07.24.

CISA ADPCVE-2026-60137: active / no / total

The values are Exploitation, Automatable, and Technical Impact respectively, timestamped Jul 21, 2026.

CISA ADPCVE-2026-63030: active / yes / total

The values are Exploitation, Automatable, and Technical Impact respectively, timestamped Jul 21, 2026.

Deployment investigation fieldPersistent object-cache state

A condition Cloudflare attaches to the anonymous 6.9+ path it described; the field explains deployment applicability, while remediation still depends on a fixed release.

6.2Event chronology

  1. Query-shape regression enters trunk

    Changeset 59766 and Git commit c22e267ccae50b45e9ae6e4b1e55ce68c408f842 introduce inconsistent array and scalar treatment during cache-key normalization; the change first ships in 6.8.0.

  2. Asymmetric batch slots enter trunk

    Changeset 60635 and Git commit 880bb48c1865b539925d901e4ddb4786457e3d05 change error handling; the change first ships in 6.9.0.

  3. WordPress ships fixed releases; CISA's initial state remains none

    6.8.6, 6.9.5, and 7.0.2 deliver the corresponding maintenance-branch repairs; WordPress recommends immediate updates and enables forced automatic updates. The late-July-17 CISA SSVC exploitation= none values now serve only as the historical state before the turn.

  4. Coordinated disclosures become public

    Searchlight reports the anonymous result on a stock plugin-free installation while withholding the technique; Cloudflare publishes its cache condition and WAF defense account.

  5. Three-request public SQL-injection detector merges

    ProjectDiscovery merges PR #16596 with a three-request flow for POST /?rest_route=/batch/v1 ; positive step-specific matchers support blind-SQL-injection reachability, and the evidence ceiling is that front half.

  6. A public implementation attempts the later chain

    98716c82d2fe9b84ff15e5f6e7aa90d30927d602 adds code for oEmbed/customize-related row reuse, administrator creation and login, plugin upload and activation, and command-output handling; the commit has no attached successful transcript or CI result, SOSEC did not run it, and this review adopts no independent reproduction.

  7. A named in-the-wild observation claim is reported

    BleepingComputer relays Benjamin Harris and watchTowr's "first signs" claim. The report provides no telemetry, IOCs, victims, request classification, or successful result, so SOSEC cannot classify the observation as scanning, attempt, or successful exploitation.

  8. CISA adds both CVEs to KEV and both ADPs turn active

    The CISA raw catalog lists CVE-2026-60137 and CVE-2026-63030 as known exploited, with due dates of Aug 4 and Jul 24 respectively; the 60137 ADP records active/no/total, and 63030 records active/yes/total.

  9. Multiple false negatives are reported for the historical SQLi template

    A PR #16596 comment and issue #16629 record that the third SQLi request does not execute under some conditions; this record limits negative interpretation for the historical 9e6cb91 template.

  10. A route-confusion template replaces the timing SQLi flow

    ProjectDiscovery merges PR #16658 (head 5d14aeb15ba2ba90ebcffa97723b63150658a97d ) and issue #16629 closes as completed; the two-request template pinned at main ref d51e9a38ae587ccdf7a75fe6aa0e11c81e7d7972 executes no SQL and uses no timing.

6.3Sources and material

  1. WordPress 7.0.2 security release noticehttps://wordpress.org/news/2026/07/wordpress-7-0-2-release/
  2. WordPress 7.0.2 version documentationhttps://wordpress.org/documentation/wordpress-version/version-7-0-2/
  3. Official WordPress release archivehttps://wordpress.org/download/releases/
  4. WordPress repository advisory for CVE-2026-60137https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-fpp7-x2x2-2mjf
  5. WordPress repository advisory for CVE-2026-63030https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-ff9f-jf42-662q
  6. CVE-2026-60137 CNA and ADP JSONhttps://cveawg.mitre.org/api/cve/CVE-2026-60137
  7. CVE-2026-63030 CNA and ADP JSONhttps://cveawg.mitre.org/api/cve/CVE-2026-63030
  8. NVD record for CVE-2026-60137https://nvd.nist.gov/vuln/detail/CVE-2026-60137
  9. NVD record for CVE-2026-63030https://nvd.nist.gov/vuln/detail/CVE-2026-63030
  10. NVD API record for CVE-2026-60137https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-60137
  11. NVD API record for CVE-2026-63030https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-63030
  12. Searchlight Cyber coordinated wp2shell disclosurehttps://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
  13. Cloudflare coordinated WordPress defense accounthttps://blog.cloudflare.com/wordpress-vulnerabilities/
  14. Official WordPress WP_Object_Cache documentationhttps://developer.wordpress.org/reference/classes/wp_object_cache/
  15. 7.0-branch REST dispatch repairhttps://github.com/WordPress/wordpress-develop/commit/85015b84fbc52bf6151a691299896b8971772594
  16. 7.0-branch batch-error slot repairhttps://github.com/WordPress/wordpress-develop/commit/c8bdf1fa12355f79db94054d307d0e3898b501c9
  17. 7.0-branch author-exclusion list repairhttps://github.com/WordPress/wordpress-develop/commit/74d37a344cbf28e9187a1a5ca71b33d186bcd333
  18. 6.9-branch grouped backporthttps://github.com/WordPress/wordpress-develop/commit/6f2074dda61864a03f334d70414d1690ce7e5c79
  19. 6.8-branch grouped backporthttps://github.com/WordPress/wordpress-develop/commit/c62f8c47314727184124b1227a00ee2eef546231
  20. Query-history commit corresponding to r59766https://github.com/WordPress/wordpress-develop/commit/c22e267ccae50b45e9ae6e4b1e55ce68c408f842
  21. REST-history commit corresponding to r60635https://github.com/WordPress/wordpress-develop/commit/880bb48c1865b539925d901e4ddb4786457e3d05
  22. Vulnerable WordPress 6.8.5 tag commithttps://github.com/WordPress/wordpress-develop/commit/a1b6ae4c8e7de4b24c2495c29aef5045338e088d
  23. Fixed WordPress 6.8.6 tag commithttps://github.com/WordPress/wordpress-develop/commit/c4ee97a868846af918b8f461b90f333687a8a81f
  24. Vulnerable WordPress 6.9.4 tag commithttps://github.com/WordPress/wordpress-develop/commit/074792ef21d9160a8fabdda215f8bf48f7a91d43
  25. Fixed WordPress 6.9.5 tag commithttps://github.com/WordPress/wordpress-develop/commit/22cfe2318f19f42e1d15a9a49e9db9f010f3afe6
  26. Vulnerable WordPress 7.0.1 tag commithttps://github.com/WordPress/wordpress-develop/commit/ca02900921c1167a1abcceeab493e2117c94d4c5
  27. Fixed WordPress 7.0.2 tag commithttps://github.com/WordPress/wordpress-develop/commit/855551c4477bd5a0407221c57dae123c4163b434
  28. Pinned WordPress 7.0.2 REST batch sourcehttps://github.com/WordPress/wordpress-develop/blob/855551c4477bd5a0407221c57dae123c4163b434/src/wp-includes/rest-api/class-wp-rest-server.php#L1746-L1848
  29. Pinned WordPress 7.0.2 WP_Query sourcehttps://github.com/WordPress/wordpress-develop/blob/855551c4477bd5a0407221c57dae123c4163b434/src/wp-includes/class-wp-query.php#L2399-L2416
  30. Pinned WordPress 7.0.2 list and integer-ID parser sourcehttps://github.com/WordPress/wordpress-develop/blob/855551c4477bd5a0407221c57dae123c4163b434/src/wp-includes/functions.php#L4979-L5010
  31. Pinned WordPress 7.0.1 REST author_exclude mapping sourcehttps://github.com/WordPress/wordpress-develop/blob/ca02900921c1167a1abcceeab493e2117c94d4c5/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L239-L270
  32. Official WordPress Posts REST API referencehttps://developer.wordpress.org/rest-api/reference/posts/
  33. Official WordPress Categories REST API referencehttps://developer.wordpress.org/rest-api/reference/categories/
  34. Unmerged ProjectDiscovery proposal 16595https://github.com/projectdiscovery/nuclei-templates/pull/16595
  35. ProjectDiscovery historical three-request detector PR #16596https://github.com/projectdiscovery/nuclei-templates/pull/16596
  36. ProjectDiscovery historical 9e6cb91 SQLi templatehttps://github.com/projectdiscovery/nuclei-templates/blob/9e6cb912c9d4df492b68ac0ecf8c333e2357de06/http/cves/2026/CVE-2026-63030.yaml
  37. ProjectDiscovery historical SQLi-template false-negative issue #16629https://github.com/projectdiscovery/nuclei-templates/issues/16629
  38. ProjectDiscovery route-confusion replacement PR #16658https://github.com/projectdiscovery/nuclei-templates/pull/16658
  39. ProjectDiscovery #16658 head commithttps://github.com/projectdiscovery/nuclei-templates/commit/5d14aeb15ba2ba90ebcffa97723b63150658a97d
  40. ProjectDiscovery current route-confusion template pinned at d51e9a3https://github.com/projectdiscovery/nuclei-templates/blob/d51e9a38ae587ccdf7a75fe6aa0e11c81e7d7972/http/cves/2026/CVE-2026-63030.yaml
  41. Pinned July 18 public wp2shell implementation commithttps://github.com/sergiointel/wp2shell-poc/commit/98716c82d2fe9b84ff15e5f6e7aa90d30927d602
  42. BleepingComputer report carrying watchTowr's attributed observation claimhttps://www.bleepingcomputer.com/news/security/wordpress-core-wp2shell-rce-flaws-get-public-exploits-patch-now/
  43. Current CISA KEV raw cataloghttps://raw.githubusercontent.com/cisagov/kev-data/develop/known_exploited_vulnerabilities.json