Skip to content

WordPress alternate-surface authorization drift wave (Sept 19 09:32Z)

Source: hourly offensive-security scan of GitHub Security Advisories, 2026-09-19 (wave published 2026-09-19T09:32Z, WPScan/WPScan-rp style descriptions).

The recurring shape: the primary UI enforces authorization; the alternate surface for the same object (REST route, AJAX action, front-end form handler, import/export job, social-login resolver) enforces nothing — or enforces a different thing. Multiple records this wave also show capability-vs-intent drift: a delegated plugin-specific permission silently carries user-management or object-ownership power the grantor never intended.

Advisory table

Plugin GHSA / CVE Boundary
Botiga Pro < 1.6.5 GHSA-vc27-9g27-3cvj REST route with no authorization check at all → unauthenticated write of arbitrary WordPress options with arbitrary values (site-takeover path), stored web scripts rendered on every front-end page, and trashing of arbitrary posts — three sinks behind one missing permission_callback.
Master Blocks < 1.5.0 GHSA-4qrp-9fm8-gvg2 Unauthenticated REST settings update; one saved value is output unescaped in wp-admin → stored XSS executing in an administrator's session (front-door input, back-office sink).
Unbounce Landing Pages < 1.1.5 GHSA-jqrj-3hxj-9rmf Subscriber can update the front-end proxy's target host → arbitrary content served from the site's own origin (trusted-origin content relay / phishing pivot).
Secure Custom Fields < 6.9.4 GHSA-6w7q-74cq-4m3f Front-end form submission never bound to the form rendered for that visitor → unauthenticated submit against any registered form → modify title/content of the post the form is bound to. Form identity is an unverified assumption.
VikRentItems < 1.2.4 GHSA-5j33-g9fw-4r4f Unauthenticated SQL injection via unsanitised parameters.
MgoSync < 2.1.7 GHSA-3j79-gfcw-gr26 Unauthenticated REST endpoint returns stored WooCommerce API credentials — read/write consumer key + secret. Integration tokens are the highest-value unauth disclosure in this wave.
Mailchimp for WooCommerce < 6.1.1 GHSA-qc48-4x35-wh3c Several REST routes' permission callbacks missing → administrator-oriented endpoints reachable unauthenticated with persistent state change.
Online Scheduling & Appointment Booking < 28.2 GHSA-mj5r-8jcf-67xr Unauthenticated AI booking-assistant conversation actions don't verify requester owns the conversation ID → read another visitor's assistant messages and inject messages into their in-progress conversation.
UsersWP < 1.5.10 GHSA-cg9c-x648-j6c7 Social login resolves an existing account by asserted email without verifying the provider confirmed ownership → log in as any user (incl. admin) whose email you can register on a supported provider. Email-assertion ATO, same family as the Sept 18 reset-link-origin items.
WP Import Export Lite < 3.9.35 GHSA-839q-664c-x9c5 Delegated plugin import permission never checked against create_users/promote_users → import can create administrators and overwrite existing credentials/roles. Delegated-capability ≠ implied-capability.
Nimble Page Builder ≤ 3.3.8 GHSA-4c39-75m8-74f3 Authenticated (Subscriber+) AJAX action returns page-builder content for any post ID → disclosure of draft/pending/private/scheduled content.
Ultra Addons for CF7 < 3.5.51 GHSA-cq73-82v9-gx86 Unauthenticated form-field upload with no type/extension validation, stored at a predictable public path with chosen extension. On Debian/Ubuntu Apache default handler config (.phar → PHP) this is RCE; elsewhere it's still a same-origin file host.
JetFormBuilder < 3.6.5.3 GHSA-mqwg-84ff-gqhv Custom field-validation callback restricted by a function blocklist that omits a file-deletion function; form managers set arbitrary PHP callbacks, and deletion fires at form submit — unauthenticated. Blocklist omission + deferred execution by a different principal.
Paid Memberships Pro (ProfilePress) ≤ 4.17.2 GHSA-jvc3-5jgr-chw6 Subscriber-level arbitrary shortcode execution (unvalidated value into do_shortcode) — adds to the Sept 19 03:32Z page's shortcode-primitive family.
Custom Field Template ≤ 2.7.8 GHSA-fv9m-mw9j-43cg SQL injection via post_ID: current_user_can('edit_post', $id) integer-casts $id for the authz check while the unsanitised string reaches the SQL sink — a type-normalization differential between the authorization check and the sink.
The Create ≤ 2.5.3 GHSA-c79v-6v55-pvvh + GHSA-jhj7-pcmr-9q9p Author-reachable REST route (publish_posts permission callback) with order_by/order SQL injection; the vulnerable branch only executes when filter params are present — trigger-precondition gating worth enumerating before concluding a query is unreachable.
The Welcomizer ≤ 2.8.1 GHSA-fmwg-rf74-rjqj Nonce-only savesection AJAX handler with no current_user_can(), and the nonce is printed to any authenticated user by a directly reachable twiz-ajax.js.php; user-supplied "custom logic" hits eval() → Subscriber → RCE. Nonce ≠ authorization; a JS asset that boots WordPress to emit a nonce is an unauthenticated nonce mint for logged-in users.
Wow Elements Addons ≤ 1.11.2 GHSA-mw9j-687w-wh97 Contributor-level SSRF: 'Changelog File' setting URL passed straight to wp_remote_get.
UsersWP-style entity: Estatik < 4.3.5 GHSA-vf6m-p9w2-rqf5 Unauthenticated AJAX reflects values decoded from a request parameter → reflected XSS (decode-then-reflect, no encode at output).
Ultimate Member < 2.13.1 GHSA-w2mq-x7qr-mgcw Profile-name value in page title: sanitizer runs before HTML-entity decoding, so entity-encoded payloads execute against every visitor incl. admins. Sanitizer-then-decode ordering is the same protect-after-use inversion as the Sept 19 WP Recipe Maker page.

Why this is worth an operator page

  • Enumerate every surface, then diff authorization. For one object type in a plugin (settings, posts, conversations, imports, forms), list transports: admin UI, AJAX actions (wp_ajax_*, both priv and nopriv), REST routes (register_rest_route — check each permission_callback), front-end form handlers, cron/import jobs. Run the same state-changing operation via each transport as the lowest-privilege principal. Botiga Pro, Master Blocks, and Mailchimp-for-WooCommerce are all "primary UI gates, REST route doesn't."
  • Delegated capability ≠ implied capability (the import/export deputy). WP Import Export Lite shows the audit rule: when a plugin defines its own permission ("can run imports"), enumerate what objects the import format can create or modify (users, roles, passwords) and check the plugin re-validates each against core caps (create_users, promote_users, edit_user). Any export→import pair (Ai1wm on the July 28 page is the same family) gets tested for the deputy jump: delegate-permission holder → admin creation.
  • Conversation/session IDs in unauthenticated actions are IDOR candidates by default. The AI booking-assistant item is the WordPress instance of the API-IDOR sweep already applied to plugins — the novelty is bidirectional: read AND inject into a live in-progress session, i.e., prompt-injection-into-another-user's-AI-agent as a bug class on scheduling/chat widgets. Sweep any action= handler taking an ID with no nonce/ownership tie.
  • Email assertion in social login = ATO oracle. UsersWP's rule generalizes to every WordPress social-login plugin in scope: after provider auth, does the app trust the provider-reported email to resolve an existing account without an ownership challenge? Test in a lab with your own accounts on two providers pointed at a staging install — register the victim-lab-user's email on your provider account and attempt login. Never test against a third-party account.
  • Type-normalization differentials between authz check and sink. Custom Field Template: the gate sees (int)$id, the query sees the string. On any parameter feeding both a current_user_can(...) call and a query, probe with values whose integer cast and string form differ (1 OR ..., padded/whitespace forms) — same class as the WordPress-core casting items on the Sept 18 core page.
  • Handler-config as exploit amplifier. The CF7-addon upload becomes RCE only because Debian/Ubuntu Apache maps .phar to PHP. Operator rule: predictable-path arbitrary-extension uploads are always a same-origin hosting primitive; the RCE claim requires proving the target's handler mapping (request the stored .phar/.phtml back and observe parse vs serve behavior with an inert file).
  • Deferred-execution callbacks. JetFormBuilder: a privileged config action (setting a validation callback) is executed later by an unauthenticated form submit. When auditing form platforms, treat any "admin configures a callable" feature as a two-stage primitive: chainable with any social-engineering or stored-config vector, and its blast radius fires at attacker-chosen time.

Validation workflow (authorized scope only)

Lab installs, disposable objects

Disposable WordPress installs with the vulnerable plugin versions, synthetic users/roles, lab provider accounts for social-login tests, inert .phar/.php marker files (no shell code), and synthetic posts/conversations. Never overwrite real user credentials, never run credential-bearing REST dumps against production.

  1. Transport diff: for each plugin surface discovered, replay a state-changing operation as (a) anonymous, (b) Subscriber, (c) owner-user. Evidence: verdict table transport × role × result. Positive controls on own objects.
  2. Import deputy test: with a delegated-import-permission lab role, import a synthetic XML/CSV containing an admin user creation + a password change on a second lab admin account you own. Record success + fixed-version behavior. Delete synthetic users after.
  3. Conversation IDOR: two lab browsers, two synthetic conversations; browser B replays A's conversation-ID actions for read + inject. Evidence: message visible/injected in A's session with synthetic text only.
  4. Social-login ownership: staging install + two provider accounts you control; assert lab-user-B's email from provider account A; record login verdict.
  5. Cast-differential probe: submit <numeric> <sql-canary> variants of any ID parameter paired with an authz check; compare authz verdict vs query behavior via benign time/error-free boolean canaries on your own rows.
  6. Upload handler test: upload inert marker with .phar/.phtml/.php.jpg variants to predictable-path uploaders; record stored path, served-vs-parsed behavior (marker prints nothing; parse is detectable by response-type/no-exec), and delete immediately.

Tracked without publication

  • Totolink A3002MU formWlWds buffer overflow CVSS 10.0 (GHSA-gc8g-58xw-mmmf / CVE-2026-93741) — the same router product already tracked from the 03:32Z/06:32Z waves; no new operator axis beyond the known /boafrm/ form-handlers class.
  • Datalogics Ecommerce Delivery subscriber order-create/cancel via stored logistics token + plugin-API-token overwrite (CVE-2026-9613, GHSA-2m92-vwcx-jmjg) — same missing-capability + stored-token-deputy axes covered here and on the July 28 page.
  • YS LeadGen subscriber popup-stored-XSS + option exposure pair (CVE-2026-1256, GHSA-h43h-55xh-wjgc + GHSA-48p5-g4jp-2qq5), Ibtana arbitrary post-meta write via iepa_builder key, VikRentItems disclosure, LiteSpeed Cache/Redux/MC4WP/WP Customer Reviews/Real3D/WPComplete-class XSS singles, GoPay/WP Optimizer SQLi singles, Hydra Booking trio, Empik/TikTok/Flex Import/Metasync/BlockSpare/Search Atlas missing-auth singles, Rede Itaú, AppMySite, Business Name Generator multisite XSS (admin-only, unfiltered_html-disallowed framing), OTP Login multisite admin XSS, PDF Builder — sparse product-specific items, no new axis.
  • WordLift/SSL Zen/TikTok information-exposure/open-redirect singles; Microsoft Edge UAF local privilege escalation (GHSA-h9w4-646p-4c73) — local precondition, tracked per browser-item precedent.

Reporting checklist

  • transport (AJAX action name / REST namespace+route / front-end form), auth context, permission_callback/current_user_can presence (absent vs wrong-cap vs wrong-target);
  • for deputy findings: the delegated cap name, the implied core caps crossed, and the created/modified synthetic object IDs;
  • for IDOR: both directions tested (read/inject or read/write), ID source (visible in UI, enumerable), and nonce presence;
  • for uploads: stored path pattern, extension accepted, target handler mapping evidence (served vs parsed), removal confirmation;
  • for social-login ATO: which provider, whether email-verified flag was set by provider, and the resolve-by-email code path if readable;
  • bounded impact language: arbitrary-option write ≠ RCE; same-origin file host ≠ code execution until handler parse is demonstrated; shortcode execution ≠ code execution without a dangerous registered handler.

Related pages: the Sept 19 03:32Z protective-transform-inverted page (sanitize-after-execute, hidden-field validate-skip, do_shortcode primitive), the July 28 WordPress payment/device page (export-secret deputy, nopriv upload axis), and the Sept 18 WordPress core page (transport-parity authorization drift at core level).

September 21 follow-up: sandbox-legitimacy confusion, nesting-defeated stripping, ungated export/import legs, and unscoped upload tokens (5 GHSAs + 1 sibling)

Five advisories published 2026-09-21 replay axes already on this page but each adds a distinct validation probe worth keeping:

GHSA / CVE Boundary Drift
GHSA-p33j-7gxx-7v4f / CVE-2026-92400 PayPal for WooCommerce IPN/payment notification Handler verifies the notification is a genuine transaction but not that it was confirmed in the store's configured environment or paid to the store's own merchant account → an unauthenticated buyer marks their own order paid using a real transaction from a sandbox they control
GHSA-4grg-xfv8-q8cj / CVE-2026-85113 GiveWP donor-supplied values on public pages Shortcode delimiters are stripped from donor input before rendering, but the stripping is defeated by nesting ([sh[shortcode]ortcode]-style rebirth after one-pass removal) → unauthenticated execution of any registered shortcode
GHSA-p5g8-hwm5-93cc / CVE-2026-86802 To Do List Member import routine Import action has no authorization and no nonce, and the routine fetches data from a location the caller chooses → unauthenticated arbitrary published posts + taxonomy terms (plus the fetch-target axis = SSRF probe)
GHSA-xf2r-mj9x-vg5q / CVE-2026-85010 RestroPress cart add/update Client-supplied item add-on price is never revalidated server-side → order total is attacker-chosen, down to zero
GHSA-hcgg-qj5x-56wj / CVE-2026-82187 Web to Print Online Designer uploads Uploads are unvalidated for type/extension and the protecting token is handed to any visitor who asks → unauthenticated PHP upload → RCE

New durable probes

  • Payment-integrity: verify the legitimacy tuple, not just legitimacy. The IPN item generalizes far beyond PayPal: any webhook/notification flow should be tested for four separable checks — signature/genuine-transaction, environment (sandbox vs live), recipient merchant/account identity, and amount/currency/order binding. Bug-hunt move: complete a real $0/sandbox transaction against your own lab store with the plugin pointed at live mode and observe whether the order completes. When sandbox credentials are trivially obtainable (they are), the "genuine payment" precondition collapses.
  • One-pass strip filters are defeated by nesting. Where a sanitizer removes a token pattern once (not to a fixpoint), reassembly recreates the token. Test every "delimiters are removed" claim with embedded/overlapping spellings before concluding the shortcode/XSS surface is closed. Sibling of the sanitize-then-decode differential already on this page — same ordering-class bug, different transform.
  • Sibling-leg gating asymmetry again. To Do List Member's import leg has neither authz nor nonce while the rest of the plugin presumably does; this is the ScadaBR pattern from the same wave (its /export_project.htm createExportJSON was left unauthenticated while the matching import path already called Permissions.ensureAdmin(), GHSA-w3gv-q645-g39f / CVE-2026-94148): when you find one gated action, immediately test its mirror (import↔export, upload↔download, create↔import). Export endpoints disclosing project/config content are the classic forgotten sibling.
  • Cart-price trust is order-integrity RCE-adjacent logic. Client-supplied unit/add-on prices accepted without server-side recompute remain a high-signal, low-noise ecom probe: one replayed cart request with price=0 answers it.
  • "Token protecting uploads" is only a control if issuance is gated. Web to Print hands its upload token to any visitor — treat every "capability token" as public material until you prove the issuance endpoint itself requires authorization. Combined with zero file validation this is straight unauth upload→RCE; keep the handler-parse proof standard from the CF7-addon item above.

Bounded validation

Lab installs of the named plugin versions; your own PayPal sandbox account for the environment-confusion test (never production merchant credentials); inert marker files with .php/.phar variants for the upload leg; nested-delimiter canary strings rendered to a page you own; cart replays against a lab store with synthetic products. Evidence = order-status transitions, rendered-marker presence, fetched-term IDs, stored-file paths; never real donor data or live payment material.

September 22 follow-up: render-vs-process authz parity, options-import ladders, and config-posture-gated POI (6 GHSAs)

The 2026-09-22 06:30Z WP wave replays this page's axes but contributes three genuinely new probes:

GHSA / CVE Boundary Drift
GHSA-q84q-9hmp-p3qm / CVE-2026-13355 Meta Box AIO ≤3.11.0 (Frontend Submission ≤4.5.6, User Profile ≤3.11.0) Unauthenticated → Administrator chain in three links: populate_via_query_string() in the frontend-submission component unconditionally overrides the form's target object_id from GET rwmb_frontend_field_object_id with no authorization; Form::process() lacks the user_can_edit() check that render() has, so the submit path writes through the render path's absent gate → unauth wp_update_post() overwrites the post_content of any page with an arbitrary shortcode; the mb-user-profile component then directly trusts the role and auto_login attributes of the injected [mb_user_profile_register] shortcode → register-as-admin with auto-login.
GHSA-wchw-wpj2-8j67 / CVE-2026-12470 CMP – Coming Soon & Maintenance ≤4.1.17 Missing capability check on the cmp_ajax_import_settings AJAX action → editor-level callers update arbitrary options → flip default_role to administrator + enable users_can_register → self-admin.
GHSA-wq6q-gx9m-7669 / CVE-2026-19658 Give Tributes ≤2.3.1 Unauthenticated PHP object injection whose reachability is decided by plugin configuration: the single-recipient code path applies sanitize_textarea_field() and the eCard custom-message-required path has give_clean() blanking serialized input — the sink is only live when "Allow Multiple Recipients" is ON and the custom-message option is OFF (the default). No known POP chain in the plugin itself.
GHSA-gxqc-8737-rfmf / CVE-2026-88788 Text Styler through 1.1.1 Contributor+ styling values echoed into a front-end <style> block unsanitized, and no check that the user may edit the target post → stored JS executes for every viewer including admins (low-role stored-XSS + missing-ownership pair already catalogued on this page).
GHSA-73p4-x7g3-p8jm / CVE-2026-85653 Contextual Related Posts ≤4.4.1 Author+ stored XSS via the other_attributes block parameter — a generic "arbitrary extra HTML attributes" block setting with no attribute allow-list.
GHSA-f9mc-qc82-mqr7 / CVE-2026-93655 Booking Calendar ≤11.8.3 Unauthenticated reflected XSS via wpbc_auto_fill (single-axis item, listed for completeness).

New durable probes

  • Render-vs-process authorization parity. Meta Box checks edit permission when displaying a form but not when processing it. Treat every render/submit handler pair as two independent gates: find the capability check in the render path, then call the process endpoint directly without ever rendering. Sweep process|submit|handle|save routines paired with any checked render|display routine across all form-capable plugins on the target.
  • Caller-target override parameters. A form bound to a target object must re-verify the submitter's authority over that object, not just over the form. Any ..._object_id, post_id, target_id, entity_id GET/POST parameter that selects what gets written is a horizontal-to-vertical pivot: swap your own ID for a target page's ID and watch whether the write follows.
  • Injected content is later parsed as trusted configuration. On WordPress, post content is a config language (shortcodes carry role=, auto_login=, prices, callbacks). Once you hold an arbitrary content-write primitive — however low-severity it looks standalone — enumerate registered shortcodes for privilege-bearing or fetching attributes, because the write + config-parser pair chains to admin. Report arbitrary-content-write findings with the concrete downstream shortcode-attribute chain, not as "content overwrite."
  • Options-update endpoints are privilege-escalation routes. Any import/settings-save AJAX that reaches update_option() with only a nonce present but no capability check is a two-request admin chain (default_role + users_can_register). Grep plugin source for option-name arrays fed to settings-import handlers and test each action at the lowest authenticated role with a valid nonce (public pages often mint nonces for anyone).
  • Configuration posture is part of the exploitability proof. Give Tributes is the third consecutive same-week exemplar (after Dancer2's static_handler: 0 precondition and NivoCart's chunk-count asymmetry): sibling code paths carry the sanitizers, and a settings toggle decides which path runs your input. When probing deserialization/upload/shortcode sinks, enumerate every plugin option combination that changes the code path before declaring the sink unreachable — and record which toggle state you proved in the report.
  • POI without a known POP chain is a conditional finding. Keep object-injection reports as chain-conditional: impact depends on third-party plugins/themes present on the specific target. Validate by proving deserialization occurs (timing/PHP-error/state side effect on an inert class), then state the chain precondition explicitly rather than inflating severity.

Bounded validation (September 22 items)

Lab installs at the named versions with a second disposable user as the write-target owner; prove the Meta Box chain against a page you created in the lab and stop at admin-session establishment; prove the CMP import leg with synthetic option payloads on a scratch install (snapshot the options table before/after); prove Give Tributes deserialization with an inert class name and no POP payload; contributor-level marker strings rendered to your own post. Evidence = post_content diffs, option-table deltas, new user rows with role, rendered marker presence; never live donation data or production option tables.

September 22 second-wave follow-up: admin-viewer sinks in submission reviewers, integration-credential write endpoints, and validator-shape gaps (Sept 22 09:31Z wave, 17 GHSAs folded)

The 2026-09-22 09:31Z WP-centric wave repeats this page's transport-drift axes but contributes three genuinely new primitive families plus a set of one-line probes.

GHSA / CVE Boundary Drift
GHSA-x4cv-hqr7-5rcm / CVE-2026-92438, GHSA-9248-28p4-jpfp / CVE-2026-94504, GHSA-jvgp-rj42-qjww / CVE-2026-91827 Ninja Forms 3.15.3 (three GHSAs) Anonymous public-form submissions are stored raw and re-rendered unescaped in the admin submission editor → stored XSS executing in the WordPress admin origin when an admin opens the submission (attacker knows the direct submission URL); the same unsanitized values are deserialized during admin CSV export → unauthenticated PHP Object Injection whose trigger sink is an export function. One input field, three sinks: front-end render, admin viewer, export parser.
GHSA-h8jc-c8c9-624r / CVE-2026-89412 TranslatePress ≤3.3.5 Front-end pipeline runs html_entity_decode() on input before persistence, and the original translation-memory column is deliberately exempt from kses → unauthenticated stored payload that no save-time sanitizer sees, rendered via v-html into the administrator's suggestion panel.
GHSA-9596-j6mw-33fx / CVE-2026-18345 WP User Manager ≤2.9.18 Connect::complete() hooked to admin_init — which fires for every authenticated user including Subscribers — fetches Stripe credentials from the caller's own WPUM Connect OAuth completion and writes them into wpum_settings with no current_user_can()/nonce → Subscriber swaps the site's Stripe keys for their own → all subsequent payments route to the attacker.
GHSA-rqq6-mm6q-4qqx / CVE-2025-14487 Handily ≤1.0.3 Unauthenticated modification of Stripe config (publishable/secret keys, success/cancel URLs) via payment-settings parameters → payment redirection to attacker's Stripe account.
GHSA-m3qm-2932-58gx / CVE-2025-14484, GHSA-jrhq-q5jc-pgv2 / CVE-2025-14486 Image Buzz ≤1.0.3, PixelPlay ≤1.0.2 Unauthenticated write/delete of administrator-configured third-party API keys (Pixabay/Unsplash/Pixels/OpenAI) via pixabay_api / clear_api_type parameters — integration-credential fields are just options, and options endpoints forget they hold credentials.
GHSA-m39c-xj94-687f / CVE-2026-93556 /password/guardarClau/recover endpoint Recovery JWT is verified for signature but not bound to the usuariId parameter → any valid-format token resets any account's password, including admin.
GHSA-vq82-hcfx-mf57 / CVE-2026-9231, GHSA-chrw-gf4w-fmg3 / CVE-2026-92969 WP Travel Engine ≤6.8.0 (wte_get_template), HUSKY ≤1.4.4 (shortcode param) Template-include LFI (contributor+), and unauthenticated LFI where the only gate is a nonce publicly emitted in inline front-end JS — the public-nonce-is-not-authorization axis again (The Welcomizer precedent above).
GHSA-mmq2-8hq5-2c6q / CVE-2026-15095 CTX Feed ≤6.6.43 Two-step deferred destructive traversal: REST call #1 persists the traversal payload into wp_options via save_feed_config; REST call #2 delete_feed performs the unlink() — the path validator is skipped on the second leg; deletion constrained to a feed-extension whitelist (csv/xml/tsv/xls/xlsx/json/txt).
GHSA-97h8-3g49-xmvg / CVE-2025-1280, GHSA-c2w6-7j98-2vqx / CVE-2025-1281 BM Content Builder <3.17.1 Subscriber-reachable AJAX pair: arbitrary file read (save_layout) and arbitrary file delete (remove_layout/export) — deleting wp-config.php re-opens the installer → RCE ladder from file-delete.
GHSA-m435-6crg-xq92 / CVE-2026-93836 WPC Product Bundles ≤8.6.6 qty validated by float cast — '1<img src=x onerror=…>' passes the numeric check (cast reads the prefix) while the full string is stored verbatim in _woosb_ids order meta → unauthenticated stored XSS.
GHSA-v8f2-9v32-fmmf / CVE-2026-6922 WP Table Builder ≤2.2.1 Operator-precedence bug makes a post-type authorization guard never fire (&&/|| grouping), plus a permission callback that checks plugin-role membership with no per-object check → subscriber trashes/restores any post on the site.
GHSA-hv57-w5f4-r2xr / CVE-2026-16778 Live Composer ≤2.1.21 Save-time wp_kses_post() is defeated because the payload is stored as a serialized string with no literal HTML tags for kses to tokenize; the shortcode callback then emits view_all_link/main_heading_title/button_inline_svg unescaped at render → contributor stored XSS.
GHSA-9x9f-f428-ff8p / CVE-2026-18439 Tutor LMS ≤4.0.7 Quiz-builder save handler validates only the top-level course_id/topic_id; nested question_id/answer_id/deleted_*_ids[] go straight into $wpdb->update/DELETE → instructor overwrites/reparents/deletes other instructors' questions. Parent-checked, children-trusted.
GHSA-45jh-6cpx-5764 / CVE-2026-93778 WP Yelp Review Slider ≤9.2 Payload arrives from an anonymous reviewer on a public third-party platform, ingested during the admin's routine "Download Reviews" click — effective attacker is unauthenticated with zero site interaction.

New durable probes

  • The admin review UI is an XSS sink; the admin export is a deserialization sink. Ninja Forms turns every public form field into a latent admin-session payload (and a latent unserialize() input on CSV export). Bug-hunt rule: on any form/submission platform, submit inert HTML-structural canaries (<img src=x>, "><svg) to every non-sanitized field, then check the admin viewer and the CSV/JSON export render of your own submission. The admin-origin execution claim needs the viewer URL and the admin-open event proven, not assumed.
  • Integration-credential parameters are options with extra blast radius. Stripe keys, Pixabay/Unsplash/Pixels/OpenAI keys, success/cancel URLs appear in payment/API settings endpoints that were built as ordinary settings writers. Sweep every AJAX/REST action whose parameter names match [a-z]+_api|api_key|publishable_key|secret_key|webhook and attempt write/delete as the lowest-privileged principal (unauthenticated here for Handily/Image Buzz/PixelPlay). Payment-redirect (attacker Stripe key) beats DoS (deleted key) as a report.
  • admin_init-hooked handlers are authenticated-user attack surface. admin_init fires for Subscribers hitting any /wp-admin/ page. When auditing, grep for add_action('admin_init' and read every callback for state writes without current_user_can() — WPUserManager's Stripe-connect writer is the exemplar.
  • Token-vs-target binding on recovery endpoints. A recovery token validated only for signature lets the identifier parameter select the victim. On any password-reset/recovery flow, obtain a token for your own account, then replay it with the user-ID parameter swapped — the check you're testing is "is this token for that user," which is distinct from "is this token valid." Fourth sibling of the token-link authority family (Origin-header/Host-header/origin-parameter waves).
  • Deferred-validator two-step writes. CTX Feed: persistence and consumption are two REST calls and only the first is validated. Where a settings-save endpoint stores a path/URL/ID and a different action later consumes it, test the pair: store your own marker payload via call 1 (always your own data), trigger via call 2, and observe whether call 2 revalidates. Same pattern as the config-write ladders page's ZLMediaKit item, WordPress-shaped; the extension whitelist on the delete leg is itself recon (it tells you which files the sink will touch).
  • Numeric-cast validators keep the string tail. (float)-validated parameters accept 1<img …> because the cast succeeds on the prefix while the original string persists. Any "validated as number/float/int" parameter should be probed with numeric-prefixed markup; compare the stored bytes against the cast value.
  • Serialized storage defeats tag-scanning sanitizers. wp_kses-style filters tokenize real HTML; payloads hidden inside serialized/json-encoded values sail through and unescape later. On page builders and settings blobs, submit payloads in encoded/serialized shapes and check the render leg independently of the save leg.
  • Boolean-precedence guards can be dead code. An authorization if with mixed &&/|| may never trigger. Never conclude a guard works from its presence — always run the negative control (role that should be denied, own object, then foreign object).
  • Check the children, not just the parent. Nested-ID payloads (Tutor LMS) cross object ownership whenever only the outermost ID is authorization-checked. On any tree-shaped save endpoint (course→topic→quiz→question, order→item→addon), submit your parent's ID with a foreign child ID inside the payload.
  • Imported third-party content is an unauthenticated attacker channel. Yelp reviews, feeds, oEmbed, media metadata: content ingested from public platforms often bypasses the site's own input controls because the site owner clicked "download." Treat every platform-ingest feature as unauth stored-content injection into the site's renderers.

Bounded validation (September 22 second-wave items)

Lab installs at named versions; submit only inert structural canaries (<img src=x>, no script payloads) to your own form entries and open the admin editor on your own session; prove the Stripe axes with your own test-mode Stripe account keys on a lab store, never production merchant credentials; prove recovery-token binding between two lab accounts you own; prove traversal/read/delete legs against files you created in a disposable directory outside WordPress core paths (never wp-config.php on anything you use); nested-ID tests use two lab instructors' own synthetic quizzes. Evidence = rendered-marker presence in admin DOM, key-value diffs in the options table, payment-routing observation in Stripe test mode, verdict tables per validator probe; never live submissions from real users, real API keys, or real payment material.

September 22 third-wave follow-up: template-include sinks, shortcode execution surfaces, and email-knowledge identity (Sept 22 12:30Z WP singles, folded)

Five singles from the 12:30Z wave add reusable axes:

  • Template-name parameters are file sinks. WP Travel Engine ≤6.8.0 contributor→LFI via wte_get_template (CVE-2026-9231): a low-role user supplies a template identifier that is included as a PHP path — contributor + any leg that stores a .php you can name (upload, log write, other plugin) = code execution. Audit rule: every get_template/locate_template-shaped helper whose name/path argument reaches the caller's request is an LFI candidate; probe with your own uploaded marker file and denied-include recorders, never core paths.
  • Shortcodes are a capability surface. WP Ultimate Review ≤2.4.2 subscriber→arbitrary shortcode execution (CVE-2026-92235): an unvalidated value reaches do_shortcode. Shortcodes registered by any active plugin are executable primitives (queries, links, sometimes writes); on any subscriber-reachable endpoint that renders user data through do_shortcode, enumerate installed shortcode tags and test each as the value. Prove with inert output-only shortcodes first.
  • Email-knowledge is not authorization. wpForo ≤3.1.5 subscriber takes over a guest author's post — title, body, author name, and stored owner email — by knowing the guest's email address (CVE-2026-91092), when guest posting/editing is enabled. Guest-identity flows that key on an email string rather than a issued token are claimable by any authenticated user who can guess or observe the address. Test matrix: authenticated low-role user + your own guest post + a second lab identity's guest post; check the preconditions (guest posting on) as part of exploitability proof.
  • Form-field parameters that carry object IDs cross ownership. Custom Field Template ≤2.7.8 contributor deletes arbitrary site-wide media attachments by supplying any numeric attachment ID in a file-field parameter with the delete flag (CVE-2026-12995) — precondition: your post's template has a file field with mediaRemove off (the default). Sibling of the nested-ID axis with a twist: the ID rides inside a field value, so per-field validators never see it as an object reference. Enumerate field-shaped parameters (file, attachment, media) for numeric-ID acceptance with denied-delete recorders against your own synthetic attachments.
  • Numeric ID enumeration = CRM PII oracle. WP-CRM System ≤3.4.6 contributor extracts full names/emails/phones/addresses of arbitrary contacts by enumerating contact_id (CVE-2026-9004): the record-response sweep on the WP page applied to CRM post types; report as read-only high-PII, prove with two synthetic contacts you created.
  • Subscriber-level wp_ajax_ toggle handlers without capability+nonce checks recur (ThumbPress deactivation CVE-2026-7622, RW Elephant cache toggle CVE-2026-4123) — same admin_init/AJAX axis already canonical above; each such handler is a small integrity primitive worth chaining, and deactivation handlers are notable because turning a security/sanitizing plugin off is a precondition-setter for other findings.

September 22 fourth-wave follow-up: marketplace-plugin IDOR quads — every AJAX action is a tenant-boundary test (MarketKing ≤2.1.72, four GHSAs folded)

MarketKing (WordPress marketplace/WooCommerce multi-vendor plugin) shipped four missing-authorization findings in one release, all the same shape applied to four different verbs — a template for auditing any multi-vendor/multi-tenant WP plugin (CVE-2026-93344 / GHSA-mr7p-65vm-9479, CVE-2026-93343 / GHSA-494w-928f-793q, CVE-2026-93342 / GHSA-xxjc-pqh8-8mgh, CVE-2026-93341 / GHSA-j68h-v872-356w):

  • marketking_get_page_content: subscriber supplies any vendor user ID → renders arbitrary vendor admin-panel pages (payouts, financial reports, dashboards) — read.
  • marketking_admin_vendors_ajax: no capability check → complete vendor directory dump (internal PII) — read.
  • marketking_duplicate_product: supply any product ID → duplicate any vendor's product, private metadata included, into your own vendor account — copy/exfil that persists.
  • marketking_send_refund: supply any order ID → file refund requests against any customer's order — write with money attached.

Durable axes:

  1. Marketplace = tenancy on top of WordPress, and WP core capabilities don't know about it. The plugin's vendor-admin surface authenticates via WP (subscriber = logged in) but authorization should be vendor-scoped; when the scoping check is missing, any Subscriber traverses every vendor. On any multi-vendor plugin (MarketKing, Dokan, WCFM, WC Vendors, WC Marketplace), enumerate its wp_ajax_/REST actions and test each with (a) unauthenticated, (b) Subscriber, (c) Vendor A acting on Vendor B's IDs — the (c) pair is the finding even when (a)/(b) 403.
  2. Read/copy/write ladder within one object family. Same advisory wave covering view-payouts, dump-directory, copy-product, refund-any-order means the missing check is likely a pattern (action dispatch without a shared verify_vendor_owns()), not four bugs — once one IDOR proves, sweep every action that takes an ID parameter in that plugin class before reporting; expect the write verbs to be as open as the read verbs, and lead the report with the money-moving one (refund forgery > directory dump for severity).
  3. The duplicate/copy primitive is underrated exfil. Duplicating a foreign object into your own account bypasses "read-only" reporting ceilings: the copy is yours to view, export, and keep. When a platform offers duplicate/clone/import actions, test them against foreign IDs — object-copy handlers routinely re-check nothing because "you're just copying."

Bounded validation: two vendor accounts you own in a lab store with synthetic products/orders/payout rows; prove traversal between your own vendors only, cancel any synthetic refund immediately, never touch real store data or customer orders.

September 23 follow-up: SSO assertion misbinding, fix-history regressions, and remote-cache file sinks (Sept 23 06:31Z WP wave, folded)

Seven items from the Sept 23 06:31Z WP wave add new axes; payment-gateway integrity items from the same wave are on the dedicated Sept 23 payment-cluster page.

  • Issued-identity misbinding — SSO servers leak the last authenticator. WP OAuth Server (Login with WordPress) <6.4.0 does not bind the OpenID Connect identity assertion it issues to the authorization grant being exchanged; it returns the assertion belonging to whichever user authenticated most recently (CVE-2026-82843 / GHSA-rwfr-37x7-2rr8). A Subscriber can obtain a validly signed assertion for an administrator and authenticate as them at every application that uses the site for SSO — one plugin bug delegates admin authority to the whole connected-app fleet. Audit rule: on any self-hosted IdP/OAuth/OIDC plugin, run a two-browser, two-account interleaved grant battery (A authenticates, B completes a grant, check B's id_token claims for A's identity; repeat with timing variants) — "most-recent" global state instead of per-grant state is the bug shape, and the blast radius multiplier ("any application that uses the site for SSO") belongs in the report headline. Prove with two lab accounts and a lab relying party you control; capture claim diffs, not live tokens.
  • Fix history is a recon map: re-test old CVEs and the regression window. The Directorist: AI-Powered Business Directory wave (6 GHSAs, <8.9.5) includes CVE-2026-84098 / GHSA-7mc4-vjfr-47h6 — a listing-deletion authz bypass that is an incomplete fix of CVE-2023-1889 / CVE-2023-35052 (a second, unaddressed deletion path re-enables the identical impact) — and CVE-2026-77766 / GHSA-rc7w-56jp-5gfx, where a REST collection was correctly scoped in 8.8.1 and the unscoped behavior was reintroduced in 8.9.1 (versions 8.8.1–8.9 unaffected). Durable probes: (1) for any plugin with historical CVEs, re-run the old PoC on current versions — fixes patch one path, and sibling entry points (AJAX vs REST vs admin-post) are the classic second leg; (2) for any finding, bisect affected-version ranges — a fix that later regressed means both "current is vulnerable" and "specific old range is safe," which changes exploitability claims and vendor triage. The rest of the Directorist wave repeats this page's canonical axes (subscriber SSRF via unvalidated listing URL 84046, unauth REST user-contact dump 84026, favorites route trusts target-user param 84150, order creation with arbitrary amounts attributed to other users 84027) — treat as corroboration sweeps, not new rules.
  • Obscurity plugins leak the thing they hide. Easy Hide Login <1.7 does not enforce its hidden-login protection on password-reset request paths: the standard wp-login.php flow stays reachable through reset parameters, and the returned page reflects the site's configured secret login slug (CVE-2026-84168 / GHSA-rx89-27rf-3jpj). Recon heuristic: when a target uses login-URL obfuscation (WPS Hide Login, Easy Hide Login, Rename wp-login), fuzz auxiliary flows that must stay public by design — lostpassword, register, resetpass, feed/REST auth endpoints — hidden paths are enforced on the main route, not the satellites. A leaked slug is low-severity but it converts your recon into the precondition map for every other login-surface finding.
  • Remote-file cache features are unauthenticated file-write sinks. YAHMAN Add-ons <0.9.31 caches remote files it fetches into a publicly accessible directory without validating the file type, giving unauthenticated attackers arbitrary PHP write → RCE when the feature is enabled (CVE-2026-75799 / GHSA-ppcx-fj6x-46xf). Audit rule: every "import from URL / fetch external asset / sync remote file" handler is a write to web root candidate — check the saved filename/extension handling (does the cache keep the remote extension? sanitize?) before checking the fetch itself; the fetch-then-store leg is where the sink lives, and an SSRF report that ignores the write leg under-reports the same bug. Proof: point the handler at your own HTTP server serving a .php-named inert marker; verify storage path and public reachability, then delete.
  • Unauthenticated mail-send handlers carry site-trusted templates. Forminator Forms <1.57.2.1's saved-draft notification binds neither recipient nor link to the session: both the address and the link inside the message come from the request, the authorization token is handed to the anonymous caller by the plugin, and it is unlimited-replay (CVE-2026-87074 / GHSA-4hc7-hvm3-f45g) → any visitor can make the site send its own branded template with an attacker-chosen link to any address (phishing with perfect sender reputation). Hunt shape: for every "email me this / share / notify about draft" AJAX handler, grab the issued token from the page and replay the send with foreign recipient + foreign link. The Sept 18 extract-before-verify page covers the sibling where the link authority (Origin/Host/parameter) is the flaw; here the flaw is recipient/link injection into a site-signed message.
  • Arbitrary post-meta write = cross-object primitive. WC Fields Factory <4.1.11's field-management AJAX action lets Subscribers create/modify/delete arbitrary post meta on any post regardless of ownership, including WooCommerce product pricing rules → price reduction at checkout (CVE-2026-93508 / GHSA-fmf3-2pcf-wpmg); the same plugin's post-cloning action (contributor+, no nonce) copies any private/draft post of any type into the attacker's readable view (CVE-2026-93507 / GHSA-225c-7qjr-pm2w). post_meta is the WordPress EAV store that permission layers forget: meta keys gate pricing, roles, template choices, and plugin state. Sweep any authenticated meta-writer parameter for meta_key/_-prefixed key acceptance with foreign post_id; the clone/dupe leg is the copy-exfil axis already canonical on this page (MarketKing) applied to core posts.
  • Booking Manager <2.1.21 SQLi via imported external iCalendar feed (CVE-2026-91024 / GHSA-8743-f7m5-qxwx): author-level imports a feed the attacker controls and feed field values go into SQL — third exemplar of this page's "imported third-party content is an unauthenticated attacker channel" rule, with the twist that the importer role is the attacker's foothold and the feed source is fully external; pair with the same plugin's settings-target IDOR (91025).

Bounded validation additions: two-account interleaved grant tests on a lab IdP install with a lab relying party; YAHMAN-style fetch proofs use your own HTTP server serving marker files with suspicious extensions inside a disposable cache dir you own; mail-send proofs go to mailboxes you own; meta-write and clone proofs use synthetic posts/products in a lab store, canceling any synthetic checkout immediately.

September 23 late-morning follow-up: core-hook ordering SQLi and eval() in block frontends (Sept 23 09:30Z WP wave, folded)

  • Login-page plugins inherit WordPress core's preprocessing — and their own SQL doesn't. Rename wp-login.php to anything you want ≤2.0.1 has time-based SQL injection via the log (username) parameter (CVE-2026-93368 / GHSA-4rj9-f57h-53hg, high, unauthenticated): the plugin's wp_login_failed handler builds SQL from the username, and WordPress core applies wp_unslash() to $_POST['log'] before dispatching the action, stripping magic-quotes escaping so a raw single quote reaches the handler unimpeded. Durable axes: (1) the auth-failure path is an unauthenticated SQL sink candidate — every login-page customization plugin (rename/obscure/CAPTCHA/2FA) hooks wp_login_failed/authenticate and writes attempt data; fuzz the username field with quote canaries on the failed-login path even when the login query itself is prepared; (2) core's normalization is part of your input contract — a handler that expects slashed input (the legacy WP convention) receives unslashed input from core hooks, an ordering differential that flips sanitizer verdicts; check what core already transformed before trusting the plugin's escaping story. Prove time-based blind with benign SLEEP() timing against your own lab install only; never run sleep chains against production.
  • Block-editor frontends get eval() where admin-side validation never runs. Getwid – Gutenberg Blocks ≤2.1.3 has stored XSS via the Google Maps block's customStyle attribute — the front-end mapStyles() JavaScript calls eval() on user-controlled block content (CVE-2026-5924 / GHSA-pcjw-3vmf-w7jr, contributor+). Contributor-to-XSS-on-public-pages is this page's front-door-input/back-office-sink shape reversed; the sharp general rule: gutenberg block render callbacks that ship front-end JS sometimes eval()/new Function() attribute-derived style/JSON strings that the server-side sanitizer treated as inert data. For any block-based site, enumerate block attributes reaching front-end JS (style, json, config-shaped attrs) and test whether any parser is eval() — proof = a benign object-literal marker changing rendered map/visual state, not script theft.
  • Shortcode read-path drift again. Advanced Contact form 7 DB ≤2.0.9: acf7db shortcode renders all Contact Form 7 submission data to any Contributor (CVE-2026-6831 / GHSA-8v4v-v89h-r3q8) — collected form submissions (PII) sit in a table the plugin exposes through a shortcode with no capability check; sweep every plugin that stores submissions for shortcode/view renderers gated only by "user can create a post." Same wave's remaining WP singles (subscription/XSS/enum items) tracked without publication.

September 23 late-wave follow-up: GraphQL mutation authz reimplemented worse than REST — collection-level checks and sibling-resolver drift (WPGraphQL, folded)

  • WPGraphQL 2.19.0 updatePost authorization bypass: Contributor publishes without publish_posts and edits own published posts without edit_published_posts (CVE-2026-88974 / GHSA-5mmc-8pc9-wggg, medium but high-signal): the mutation checks only the post type's collection-level capability (current_user_can( $post_type_object->cap->edit_posts )) and never performs WordPress's object-level check (edit_post, post_id), nor a publish_posts check when the requested status is publish — status passes straight through to wp_update_post(), which trusts that its caller already authorized. The plugin's own createPost resolver does the publish-capability check and downgrades unauthorized status to pending — the guard exists in the sibling code path and was not reimplemented in the second one. The WordPress REST API correctly rejects the identical operations for the same user, which the advisory itself cites.
  • Durable axes: (1) collection-level vs object-level capability checks — edit_posts ("may edit posts of this type") is not edit_post ("may edit this post"); any authorization code that only references the cap->edit_posts-shaped properties is the shape of this bug. (2) Sibling-resolver parity diff: whenever a GraphQL API exposes create/update/delete on the same object, diff their authorization code — WPGraphQL's create was correct and update was not; audit both directions (a check present in one resolver proves the semantic requirement exists, so its absence in the sibling is a bug, not a design choice). (3) REST-vs-GraphQL parity battery: on any WordPress site with GraphQL enabled, run every capability-sensitive operation twice — REST wp/v2 and GraphQL mutation — with a Contributor/Subscriber token; a REST 403 + GraphQL 200 differential is the finding, and the differential harness doubles as your negative control (same input, two routers, two verdicts).
  • Bounded validation: lab install with two contributor accounts you own and synthetic draft/publish posts; prove the status transition and foreign-object edit on your own objects first, then against a second lab account's post. Report the resolver-level code citation (collection vs object check) plus the REST/GraphQL verdict table.
  • The Newsletter – Send awesome emails ≤9.3.9 unauthenticated permanent-cookie theft via public click-tracking route (GHSA-r57r-xx5c-pcg3 / CVE-2026-92537): the public REST route /tnp/l/ is registered permission_callback => '__return_true'; on any validly signed click-tracking URL it calls set_user_cookie(), which emits Set-Cookie: newsletter=<id>-<raw_token> to whoever hit the link. The masking that should protect the credential is state-dependent: the subscriber object loaded via get_user() lacks the _trusted property on this path, so get_user_key() returns the raw token column instead of its MD5-masked variant. Any holder of one signed tracking URL (embedded in every external link of every newsletter, forwarded/screenshot/scraped by link-preview and URL-scanner services) receives the subscriber's permanent raw authentication cookie, then exports full PII (?na=px), rewrites the stored profile (?na=ps), and silently unsubscribes via the RFC-8058 one-click endpoint (?na=ocu) — none require a nonce, password, or email challenge.
  • Durable axes: (1) a signed URL is not just a redirect grant — sweep what the redirect endpoint emits back. Every permission_callback => '__return_true' route that "just validates a signature and forwards" must be checked for Set-Cookie/session-mint side effects; the signature proves the URL, not that the response is safe to hand to whoever holds it. Newsletter/email click-tracking endpoints are high-value because their URLs are mass-distributed by design and pre-fetched by link scanners. (2) Credential masking is a per-code-path property, not a per-field one. The same get_user_key() returns masked material on the normal login path and raw material on a loader path that skips the _trusted flag — when auditing any token/cookie emission, trace the object loader used by that path and compare what masking conditionals gate on; hunt the sibling loaders that don't set the flag. (3) Cookie-steering probe for WP newsletter/marketing plugins (MailPoet, Newsletter, Email Octopuses shapes): submit a signed or unsigned tracking hit with curl -v and inspect response headers for identity-bearing Set-Cookie before concluding the route is a benign redirector.
  • Bounded validation: lab install with your own subscriber record; generate your own newsletter, hit your own tracking URL with a header-logging client, confirm the cookie equals the raw token column in the DB you dumped from your own lab, replay ?na=px against your own subscriber only, then delete the synthetic subscriber. Never collect real subscribers' tokens or open real user profiles.

October 1 late-morning follow-up: registration mass-assignment, self-target capability collapse, and no-role-check login-as (Oct 1 10:30Z WP wave, folded)

  • Super Forms ≤6.3.316 unauthenticated Administrator registration via role= mass assignment (CVE-2026-15989 / GHSA-mjx4-cmxj-rrrw, critical): the Register & Login add-on's before_email_success_msg() whitelists the client-submitted role key and copies it into the user-data array passed to wp_insert_user() — no validation against the admin-configured register_user_role, no allow-list, no current_user_can(). Inject role=administrator into the data submitted to any published registration form → Administrator account, no credentials needed. Same plugin, second bug: the super_save_form AJAX handler has no capability check (Subscriber can create/modify forms and flip settings), and super_submit_form passes attacker-controlled files[].subdir into SUPER_Common::delete_dir(); the ABSPATH containment guard dies to a trailing-slash mismatch — subdir=wp-config.php makes dirname(realpath(ABSPATH.$subdir)) equal the WordPress root while the naive ABSPATH !== $dir string compare passes → Subscriber-driven recursive arbitrary file/directory deletion, site takedown, and reinstall-path RCE.
  • WPC Shop as a Customer for WooCommerce ≤2.0.0 login-as-admin with no password (CVE-2026-95687 / GHSA-wcrr-q656-8gwf, high): the wpcsa_login endpoint issues a fresh authentication session for any user ID supplied directly in the request without validating the caller's authority over the target role — supply an Administrator's user ID, receive a full Administrator session cookie.
  • ByteCoreStack MCP Connector ≤1.2.3 Subscriber→Administrator through its own MCP JSON-RPC tool (CVE-2026-19807 / GHSA-qwvr-5fhh-47xh, high): wp_update_user_meta gates writes with current_user_can('edit_user', $uid) — which WordPress core's map_meta_cap downgrades to the read primitive when $uid equals the caller's own ID — while the meta-key blocklist covers only user_pass, user_activation_key, session_tokens. A Subscriber calls the MCP tool with key=wp_capabilities, value={'administrator':true}, own user ID → loads as Administrator next request.
  • Autoptimize ≤3.1.15.1 stored XSS via REQUEST_URI path (CVE-2026-14995 / GHSA-v9f4-5xpx-364q, high, unauthenticated): the Critical CSS feature queues the request URI into cache entries rendered on the front end; precondition is Critical CSS active with a valid API key — a feature-flag precondition gates the vulnerable path, enumerate optional features before concluding an input never reaches output.
  • Durable axes: (1) Registration-form payloads are mass-assignment surfaces — sweep every field name a registration/checkout handler echoes into wp_insert_user()/wp_update_user(); role=, role[]=administrator and wp_user_level=10 belong in the canary set, and the fix is always an allow-list of accepted keys, not a denylist. (2) Self-target capability collapse: current_user_can('edit_user', get_current_user_id()) is nearly always true because core maps self-edit to read — any tool that lets a user edit themselves must additionally denylist (better: allowlist) the meta keys it accepts, and wp_capabilities/wp_user_level/wp_user_settings are the privilege keys to probe; blocklist-shaped defenses get swept for the omitted key (this wave's blocklist omitted exactly the two that matter). (3) "Login as" / impersonation endpoints (customer-service, support, agency plugins) are role-confusion gold: test whether the endpoint validates authority over the target, not just caller authentication, by requesting a session for a second lab account's ID. (4) Trailing-slash guard differential (realpath + dirname vs the constant's trailing /) is the prefix-containment family again — on every path guard, test the bare child of the root (subdir=wp-config.php shape) where dirname() collapses onto the root itself. (5) AI-connector plugins are WP privilege surfaces: a WordPress site exposing an MCP/LLM tool bridge doubles the plugin's attack surface with a machine-driven caller that never sees UI prompts — enumerate /mcp-style JSON-RPC endpoints and run the same role/meta canaries there.
  • Bounded validation: lab install, your own two accounts (Subscriber + disposable Administrator), synthetic forms; prove the role= injection on your own registration form, the self-meta write on your own user row, and login-as against your own second account; deletion proofs only against marker files inside a scratch directory, never wp-config.php even in a lab that matters.

October 1 12:31Z follow-up: publicly minted nonnes defeat the "nonce = auth" assumption (Forminator, folded)

  • Forminator Forms ≤1.57.2 unauthenticated stored XSS via freely-mintable AJAX nonce (CVE-2026-92144 / GHSA-pg8f-q234-6933, high): stored XSS through the postdata-1[post-custom] parameter; the form-submission nonce the handler requires is handed out by the publicly accessible wp_ajax_nopriv_forminator_get_nonce endpoint — so the whole chain runs with zero authentication and zero account. Durable axis: a nonce fetched from a nopriv action is not an authorization signal — when auditing any WP form plugin, grep its handler registration for wp_ajax_nopriv_ endpoints that issue nonces/tokens the submit handler then demands; that pairing collapses the CSRF control into a two-request formality for unauthenticated attackers. Sweep canary: action=<plugin>_get_nonce posted to /wp-admin/admin-ajax.php as anonymous — any 200 with a token string in the body means every "protected" submission endpoint behind it is unauthenticated attack surface. Bounded validation: lab install, your own form, inert marker payload in your own post, confirm execution only in your own browser profile.
  • DevKit Pro ≤2.3.0 unauthenticated Administrator ATO via forgeable original_user_id cookie (GHSA-xwfv-9j83-wfj7, 9.8): the revert_switch handler (a user-switching/impersonation feature) derives the "privileged identity" from an attacker-controlled cookie: verify_nonce_and_capability() checks manage_options on the user named by the cookie instead of calling current_user_can() on the actual requester — and the switch-back form plus a valid session-bound nonce is emitted into wp_footer to any visitor, unauthenticated included, whenever that cookie is present. Recipe: set original_user_id=<admin id> → page renders with the admin's revert form + nonce → POST it back → wp_set_auth_cookie() for the admin. Durable axes: (1) capability checks must bind to the authenticated principal, not a request-supplied identity token — audit any current_user_can($cap, $id) where $id comes from cookie/parameter instead of the session; checking a capability on the victim proves nothing about the caller; (2) state-conditional privileged UI fragments leak to anonymous callers — if markup (with embedded nonces) is gated by a cookie rather than by the session, an attacker can trigger the gate for themselves; sweep "switch back / return as / undo impersonation" affordances by setting the steering cookie on a logged-out client and grepping the response for nonces. Same family as the Oct 1 WPC Shop login-as finding: impersonation features carry their own second-order auth surface.
  • Ninja Forms – File Uploads ≤3.3.34 stored path read/written/deleted by later lifecycle stages (External S3 flow) (GHSA-3v9p-5xxf-6hxg, 8.1): the form submission carries an attacker-supplied file path that is stored verbatim as file_path, then dereferenced without validation by three later consumers — the notification-email attachment (arbitrary file read), the external-store fetch (arbitrary file write, RCE when S3 action configured), and scheduled cleanup (arbitrary file delete). Durable axis: a path stored at input time is a deferred primitive — validation at form-submit time (or none, as here) is irrelevant if the consumers re-dereference the stored string; when auditing form/upload plugins, grep where file_path-shaped columns are read back (mailer, sync, cron/GC) and test the read/write/delete legs from the stored row, not just the submission. Precondition reporting matters: the write leg requires the External (S3) upload action configured, the read leg also needs an email action attaching the file.
  • Super Forms ≤6.3.316, two more legs (third and fourth bugs on this plugin's audit ladder, after the Oct 1 role= + delete_dir items above): (a) Subscriber→any-account credential takeover (GHSA-h8h9-7p7r-7rpq, 8.8) — the Register & Login add-on's register_login_action='update' flow trusts an attacker-supplied user_id into wp_update_user() with no ownership check, and because super_save_form itself has no capability check (Oct 1 finding), the Subscriber creates the malicious form then submits it with an admin's user_id + new password → full account takeover; the two bugs compose — form-builder freedom + update-flow identity trust = privilege chain neither half alone. (b) Unauthenticated arbitrary file read via parse_request traversal (GHSA-r39q-9952-j46j, 9.1) — the file_upload_auth setting defaults to empty (no auth required); the traversal needs a real 13-digit timestamp upload directory, and the plugin's own file-upload response returns the created directory name — the feature hands you the oracle needed to exploit its own traversal. Durable axes: default-empty auth toggles mean the default deployment is unauthenticated (enumerate plugin settings whose empty value disables a gate — *_auth, *_key, whitelist); and check whether a sibling feature discloses the identifier a path check assumes unguessable. Fix-precondition note for reports: enabling the setting mitigates unauth access but does not fix the traversal itself — test authenticated too.
  • SiteOrigin Widgets Bundle ≤1.73.2 LFI via a legacy undeclared field (GHSA-vc58-2rcj-cgf8, 7.5): POSTing widgetData with a legacy top-level theme key alongside a non-empty columns array to /wp-json/sowb/v1/widgets/previews bypasses validation entirely because update_fields() only iterates declared form fields — the undeclared legacy key still reaches the widget renderer, which includes the path as PHP. Contributor-level → code execution. Durable axis: validation loops over the current schema; renderers often still honor legacy/undeclared keys — mass-assignment's WordPress flavor: fuzz documented-in-changelog-but-no-longer-in-the-form parameters, and compare "keys the validator iterates" vs "keys the renderer reads"; the delta is unvalidated reachable input.
  • RafflePress <1.12.27 reCAPTCHA secret key published in public giveaway settings (GHSA-82gv-pr29-8vm2): the plugin embeds the server-side reCAPTCHA secret in the settings blob on public giveaway pages. Durable heuristic: on pages embedding a client-side config/JSON blob, diff returned fields vs fields the UI actually renders — server-only secrets (recaptcha site/secret pairs, API tokens, provider keys) leak wholesale when a plugin serializes its options object instead of an explicit view model. Same raw-serialization disclosure family as the Oct 2 PictShare info-endpoint item; sweep wp_localize_script/inline {"settings": payloads for _key|_secret|_token names.
  • Bounded validation: lab installs with disposable accounts; DevKit-style cookie proofs use your own admin account ID and revert immediately; Super Forms traversal reads synthetic marker files you uploaded to your own lab; RafflePress checks are your own lab giveaway page's embedded blob; SiteOrigin inclusion proofs use an inert marker .php you uploaded in the same lab.

October 2 late follow-up: client-driven checkout state machine, entity-encoded sanitizer bypass, and regex-gated header echo (Oct 1 09:30Z GHSA sync wave, folded)

  • Ultimate Multisite ≤2.15.0 unauthenticated ATO of any user by email address (CVE-2026-75957 / GHSA-xr7j-wm8w-c5p4, 9.8): the public wp_ajax_nopriv_wu_validate_form handler accepts a freely obtainable checkout nonce, and the checkout_form=wu-finish-checkout parameter makes get_validation_rules() discard all validation rules while finish_checkout_form_fields() returns an empty step list — is_last_step() then returns true and the request routes straight into full order processing. maybe_create_customer() resolves the attacker-supplied email_address to an existing WordPress user ID with no authentication or ownership check, and login_customer_after_checkout() calls wp_set_auth_cookie() — full session for the victim. Durable axes: (1) client-supplied state tokens that select the validation branch — a step/flow parameter (checkout_form, step, stage) that makes the validator return an empty rule set is an auth bypass wearing a workflow costume; sweep every multi-step form handler for parameters that index into a step→rules map and test the terminal/unknown step where the map returns nothing (empty rules + "is last step?" = skip-to-finish); (2) identifier resolution as credential: any flow that maps an email/username to a user ID and then acts as that user (auto-login, order attribution, invite acceptance) treats "knows the email" as authentication — test with your own second account's email on a lab checkout; (3) public-nonce + nopriv handler composition is the Forminator axis (Oct 1) reaching authentication rather than stored XSS — the same two-request formality now mints cookies.
  • PDF Invoices & Packing Slips for WooCommerce ≤5.16.1 unauth stored XSS through entity-encoded billing names (CVE-2026-92244 / GHSA-v7w7-gmmm-67f2, 7.2): sanitize_text_field()/wc_clean() do not strip entity-encoded strings containing no literal < character, so a guest-checkout order plants payload in Billing First/Last Name/Company that executes whenever an admin opens the order. Sanitizer-class axis, new encoding leg: a store-time filter that blacklists literal characters (<, ") misses &lt;script&gt;-style or double-encoded shapes when the render-time context decodes them. Sweep canary for every free-text field that reaches an admin screen: submit &lt;img src=x onerror=...&gt; and &amp;lt;svg onload=...&amp;gt; shapes via guest checkout/registration, then open the admin view — the payload surviving storage and executing on render proves the store/render decode mismatch. This is the sanitize-then-decode family (Ultimate Member, Sept 19) reached by the input instead of the storage layer.
  • Ad Inserter ≤2.8.18 reflected XSS via Referer header, gated by a search-engine regex (CVE-2026-19902 / GHSA-298r-885r-pj27, medium): when an ad block's code contains the {search-query} dynamic tag, replace_ai_tags() reads $_SERVER['HTTP_REFERER'], tests it against /[\.\/](google|yahoo|bing|ask)\.[a-z\.]{2,5}[\/]/i, and echoes the match — header content that satisfies a look-valid regex gets reflected unsanitized. Durable axis: conditional-echo gates on attacker-controlled headers are satisfiable by design — a if (preg_match('/google|bing/', $referer)) echo $referer shape has an attacker-controlled gate; enumerate every header the app reflects (Referer, X-Forwarded-*, User-Agent in debug panels) and supply payloads that include the expected look (https://google.com/ prefix + payload). Adjacent same-plugin item CVE-2026-89427 / GHSA-cjx2-r3r5-6cq4 (reflected XSS via s search parameter) is the un-gated sibling of the same tag renderer.
  • LearnPress ≤4.4.8 IDOR through an explicitly no-nonce AJAX allowlist (CVE-2026-93882 / GHSA-hgjr-485v-48f2, high): CourseMaterialTemplate::render_material_items() is exposed on the public lp-ajax-handle (load_content_via_ajax) endpoint, listed in the framework's AbstractAjax no-nonce allowlist, with no capability check on the course/id arguments → unauthenticated read of course material by ID. Sweep rule this adds: in any plugin with an AJAX framework that dispatches by action to per-callback classes, find the framework's own "skip nonce" list (a constant/array in the abstract class) — every callback on it is unauthenticated surface regardless of what the individual handler author assumed; enumerate allowlisted action names from the class source on open-source plugins, or black-box probe them against the single shared handle endpoint.
  • Bounded validation: lab multisite with your own two accounts (prove the email-resolution login against your own second account and revert); guest-checkout XSS payloads rendered only in your own admin profile; Referer/XSS canaries only on lab installs; LearnPress IDOR proven with a synthetic course you created.

Tracked without publication (same Oct 1 09:30Z sync wave): Form Maker 10Web map-lat/long stored XSS (GHSA-6hr3-5gmx-jj2q), Forminator RTE-textarea stored XSS (GHSA-p5j2-g3x4-wqgf, RTE axis canonical), Appointment Hour Booking DOM-XSS via schedule renderer (GHSA-8899-xhvc-pc43), Calculated Fields Form reflected DOM-XSS via url.<name> predefined value (GHSA-fqpx-ff2f-3pfw), Redux user-meta-merge XSS (GHSA-8g8c-pxm3-p2hh), Duplicate Post noti_token XSS (GHSA-mjxg-mhjq-2vx5), Awesome Support gdpr-data XSS (GHSA-rgpg-j229-6w44), Business Essentials CF7 gateway-field XSS (GHSA-h887-w8fc-499x), bbp style pack display-name+reply XSS (GHSA-3qmp-qqq9-w2h8), Social Media Share Buttons mobile-gated reflected XSS (GHSA-85vv-xjp4-x52m), Ad Inserter s-parameter reflected XSS sibling (GHSA-cjx2-r3r5-6cq4) — XSS-class already canonical; MISP analyst-notes + legacy-taxonomy reflected XSS (GHSA-66pp-jmhc-r9mv, GHSA-p9m5-xwgx-8j69) — reflected-XSS singles on a page whose axes are already published; OpenConstructionERP AI-provider config wrong-session disclosure (GHSA-8rwg-xf8h-29m3, detail-thin); Fuji Apeos printer web-UI traversal (GHSA-vmmg-gmvf-x548, generic printer-traversal class); Android SettingsLib/AccessibilityManager/CredentialManager/Biometric logic singles (June-dated re-surfacing, processed class).

October 2 06:30Z wave tracked without publication

  • Ninja Forms ≤3.15.4 RTE-field stored XSS (GHSA-7cq6-x444-93vj) — unauth stored XSS when a Paragraph Text field has RTE enabled; sanitize-skip-on-optional-field axis already canonical here (Sept 22 Give Tributes config-posture-gated pattern).
  • Autoptimize ≤3.1.15.1 comment-author-name stored XSS (GHSA-fcq7-9xcx-6xxw) — sibling of the Oct 1 Autoptimize REQUEST_URI item already on this page; lazy-load precondition gating is the same feature-flag axis.
  • RafflePress <1.12.27 unvalidated parent-page URL → site-origin redirect chain (GHSA-9949-jq7q-8g48); OMGF <6.3.11 unauth no-nonce slow loopback request DoS (GHSA-87mc-m7h4-wxp9) — DoS with no extraction leg, tracked per precedent; Popup Maker ≤1.4.5 nonce-only subscriber site-option overwrite (GHSA-f5pm-cq7v-xmjw) + Request a Quote ≤2.5.6 unauth AJAX contact-record read (GHSA-24j4-6qf8-p4rw) — nonce≠auth and unauth-read axes canonical; Motors listing-metadata IDOR (GHSA-whfp-wchg-v9xw, non-default config) + badge-setting XSS (GHSA-h25v-5897-j3vf); BuildKit <1.0.29 contributor stored-SQLi executed on public view (GHSA-564m-jf3j-p556) — deferred two-stage shape noted but SQLi-class already canonical; CTX Feed Pro ≤7.6.12 admin eval() (GHSA-m8mq-x2gc-8xcm, admin-only); Visitors Traffic Real Time Statistics Pro ≤11.22 nopriv page_title unauth stored XSS → admin dashboard innerHTML (GHSA-x36m-2pwv-jrpp) — front-door-input/back-office-sink exemplar, axis canonical; Avada lang R-XSS, Unlimited Elements icon-attribute XSS, Tabs Responsive shop-manager product-tab XSS — generic sanitizer singles.

October 2 09:31Z follow-up: response-cache keyed on URI alone serves minted admin cookies to anonymous GETs (JSON API Auth, folded)

  • JSON API Auth ≤3.1.2 unauthenticated Administrator session theft via cached cookie-minting response (CVE-2026-97637 / GHSA-pmrp-gw7x-5x4r, critical): the PI-Media/json-api parent plugin caches controller dispatch results in transients keyed solely by URI + query string — ignoring HTTP method and POST body. Its generate_auth_cookie() endpoint embeds a live logged_in cookie (wp_generate_auth_cookie()) directly in the JSON response body; after an administrator POSTs to /api/auth/generate_auth_cookie/, any subsequent unauthenticated GET to the same URI replays that cached authenticated response for the 24-hour TTL → full admin session. The plugin's nominal HTTPS enforcement gate is bypassed by supplying insecure=cool as a request parameter (the literal vendor backdoor string). Durable axes: (1) response caches keyed on URI alone collapse method and body into identity — any POST-mints-a-secret endpoint behind a URI-keyed cache layer becomes a public GET-replayable secret; enumerate cache/CDN/transient layers per endpoint and test GET-replay of POST responses; (2) response-body credential embedding: wp_generate_auth_cookie() output in a JSON body is a cookie regardless of transport — sweep API responses for logged_in/auth_cookie/token fields and treat them as session material; (3) hardcoded bypass params survive as permanent backdoors — grep plugin source for magic parameter values (insecure=, debug=, dev=) on every API plugin; the cache-replay precondition (an admin POST inside the TTL) makes this a wait-and-replay attack on active admin panels, worth reporting with the TTL window stated. Bounded validation: lab install, your own admin account POSTs the endpoint, anonymous second browser replays the GET; prove cookie validity on your own get_currentuserinfo; delete transients after.

October 2 15:31Z follow-up: bcrypt-comparison role resolution turns a locally-computed hash into an admin registration (Divi Membership, folded)

  • Divi Membership ≤2.2.0 unauthenticated administrator registration via attacker-supplied bcrypt hash (CVE-2026-19652 / GHSA-f7mc-wpjj-g5hj, 9.8): dmem_form_submit_handler() decides the new user's role by iterating all WordPress roles and calling password_verify() against a bcrypt hash the attacker supplies in the form_id POST parameter — no role whitelist. Submit a locally computed bcrypt hash of the string administrator as form_id, and you register as an admin; with auto_login=on the same request returns an authenticated admin session. The required nonce is publicly emitted on any page rendering the registration form, so the nonce gate is decoration. Durable axes: (1) value-comparison-as-authorization across an unbounded candidate set — when a handler loops over privileged candidate values and tests attacker input for a match (hash-compare, token-compare, secret-compare), the attacker who can pre-compute the match chooses the outcome; enumerate every parameter whose value is compared rather than looked up, and ask what happens if the attacker guesses the compare target (password_hash('administrator', PASSWORD_BCRYPT) is trivially computable because the "secret" is a public role name); (2) publicly-minted nonces again (Oct 1 Forminator sibling on this page) — confirm the nonce's issuance page is reachable unauthenticated before crediting it as authz; (3) combined state transitions in one request (auto_login=on) mean privilege escalation is immediately used, not staged — test whether escalation endpoints also emit the session. Bounded validation: lab install, register your own admin account via the form-parameter shape, document role table before/after, delete the account.

October 3 03:31Z follow-up: AJAX directory endpoint skips the field-level visibility model the profile page enforces (Ultimate Member, folded)

  • Ultimate Member ≤2.13.1 unauthenticated read of privacy-restricted profile fields (CVE-2026-93428 / GHSA-mx72-jqqr-rmpp, 7.5): fields configured owner-only, members-only, or role-restricted on the rendered profile page are returned in clear by the public wp_ajax_nopriv_um_get_members endpoint — the directory AJAX handler applies none of the visibility model, and its only gate is the um-frontend-nonce, which wp_localize_script emits to anonymous visitors, so the endpoint is unauthenticated end to end. Durable axes: (1) visibility/privacy models live in the render path; AJAX/REST siblings return the raw object — for every field-level privacy toggle a plugin offers, enumerate which endpoints can return that field and re-read the same object through each (profile page vs directory AJAX vs REST vs export); a privacy setting tested only on its own page is unverified. (2) wp_localize_script-emitted nonces are public constants — before crediting any nonce as an authz gate, fetch the issuing page with no session and grep for the nonce value (this page's The Welcomizer / HUSKY / Welcomizer-family rule, now with a localize-script minting vector). Sweep shape: on any UM (or membership-plugin) target, request action=um_get_members with the page-extracted nonce and diff returned field keys against what the same profile renders anonymously. Bounded validation: lab install with a disposable member account and synthetic field values; enumerate field keys and presence/absence only; never harvest real member PII beyond confirming your own canary values.

October 3 06:31Z follow-up: recipient-parameter override, upsert-leg guard gap, attacker-chosen deferred SQL trigger, and fallback-extractor hardening gap (Oct 3 06:31Z wave, folded)

  • Simple Membership ≤4.8.3 unauthenticated activation-email recipient override → plaintext-credential theft (CVE-2026-97337 / GHSA-7wr9-4367-v9vm): the resend-activation/email-activation endpoints dispatch from SwpmInitTimeTasks::check_and_do_email_activation() on frontend init with no auth, nonce, capability, or ownership check, and the recipient used by send_reg_email() is taken from attacker-controlled $_POST['email'], overriding the pending member's registered address. The redirected "registration complete" email contains the member's username and plaintext password, and the attacker can then activate the victim's account. Durable axes: (1) notification handlers that take the recipient from the request are recipient-swap oracles — for every resend/notify/forward action, diff the recipient actually used against the object owner; the parameter names to sweep are email, recipient, user_email alongside the ID that identifies whose notification it is; (2) plaintext passwords in transactional email are a standing ATO primitive — when any plugin email contains credentials, the recipient-override bug converts a mail-flow flaw into account takeover without touching the password store; fingerprint plugins that build "your login details" emails.
  • Groundhogg ≤4.9 contact identity rebinding via upsert-vs-update guard parity (CVE-2026-97644 / GHSA-9c9v-5p57-4qfm, 8.8): POST /gh/v3/contacts is gated only by add_contacts and forwards the full payload including the security-bearing user_id column into Contacts_DB::add()'s upsert path, bypassing the ownership guard that Contacts_DB::update() enforces — a Sales-Rep can rebind any existing contact row to an Administrator's user ID, then invoke the v4 POST /gh/v4/emails/test endpoint which acts under the bound identity. Durable axes: (1) add/upsert legs routinely lack the guard the update leg has — the create-side mirror of this page's sibling-leg rule; whenever you find update()/save() with an ownership check, test the create/upsert/import leg with the same guarded column present in the payload; (2) CRM contact→user-ID bindings are identity links — rebinding an entity you legitimately hold to a privileged user ID makes every later feature that "acts on behalf of the contact's user" (email sends, automations, API tokens) run as that user; enumerate every consumer of a rebinding-able FK before reporting the write alone.
  • GeoDirectory ≤2.8.186 stored-coordinate SQLi with attacker-chosen public trigger (CVE-2026-103913 / GHSA-285m-c668-wj9h): lat/long values are saved with no numeric validation, then geodir_gps_query_part() string-interpolates the stored values into a distance sub-expression executed by the public wp_ajax_nopriv_geodir_widget_listings handler when a caller supplies set_post=<pending-listing-id>&sort_by=distance_asc. A Subscriber plants the payload; the SQL runs in an unauthenticated context the attacker picks the moment and endpoint for. Durable axis: deferred-SQL with trigger selection — the save leg never executes the payload (prepared or escaped at write time is irrelevant), and the consuming leg trusts stored bytes; sweep every sort/distance/nearby query parameter that references a stored object ID, and treat "stored value + expression-building consumer" as the SQLi shape even when the writer looks prepared. Sibling of the Ninja Forms file_path deferred-consumer rule (Oct 2) with SQL as the sink.
  • Unlimited Elements for Elementor <2.0.21 archive extraction RCE only on the fallback extractor (CVE-2026-85015 / GHSA-q6fg-7vp2-c3xp): uploaded archives are extracted without path sanitisation on servers where the PHP zip extension is unavailable — the fallback extraction code path preserves traversal separators and writes executable PHP outside the upload dir. Durable axis: the fallback/secondary parser is the unhardened one — primary paths (PECL zip, cURL with options, image libs) accumulate sanitizer fixes; fallbacks (PclZip, manual TAR readers, pure-PHP parsers) ship as "compat shims" without the same guards. When a feature behaves safely on your fully-patched lab box, enumerate the feature-detection branches (extension_loaded, class_exists, function_exists) and reproduce in the degraded environment (disable the extension) before concluding the sink is closed. Same family as the Composer symlinked-bin fix-bypass and provider-conditional XML hardening lessons on the July 31 library page.
  • WP 2FA <4.1.0 TOTP replay: validate-without-invalidate (CVE-2026-103514 / GHSA-fh83-crgf-9w82): a time-based one-time passcode is not marked used after acceptance, so anyone who knows the account password and observes one valid code inside its window can replay it — including against admin accounts. Durable axis: OTP controls are only "one-time" if the server consumes them — for any 2FA plugin/flow, prove single-use by completing a lab login, then replaying the same code inside the window; the probe costs one extra request and separates genuine MFA from replayable MFA. Reports should state the observed window and whether replay survived a concurrent login.
  • Visitor Traffic Real Time Statistics ≤8.16 unauthenticated stored DOM-XSS via X-Real-IP header (CVE-2026-97341 / GHSA-4mc8-9rx9-vcjv): the wp_ajax_nopriv_ahcfree_track_visitor endpoint accepts a forged X-Real-IP from any anonymous request and stores the entity-encoded payload verbatim, rendered later as DOM. Axis: tracking/analytics endpoints store request headers as user data — visit-trackers persist header-derived "visitor" fields (IP, UA, referer, X-Real-IP, X-Forwarded-*) that dashboard views later render; add every header to the stored-input canary set on nopriv tracking actions, not just body parameters.
  • Kubio AI Page Builder <2.9.3 editor-scoped HTML allowance applied to unauthenticated submissions (CVE-2026-88783 / GHSA-w96f-q24m-hc95): the plugin widens its allowed-HTML element set for the editor context but doesn't scope the widening to it — unapproved unauthenticated submissions keep markup that the plugin's own front-end script later executes. Axis: sanitizer allow-list widenings inherit to every role/path unless explicitly scoped; test the lowest-trust submission path against the widest policy. Tracked adjacent: same-plugin contributor URI-scheme link XSS (GHSA-gf46-mg37-6fp9).

Same wave, tracked without publication on this page's canonical axes: TillKit <1.0.5 hardcoded publicly-known POS PIN authenticates a privileged session (identifier-as-credential, July 30 EV page rule); MPG <4.2.3 dataset-source URL-vs-path type confusion copying arbitrary files into public uploads (file-copy relay, tracked); Loco Translate <2.8.9 translator-cap file read outside webroot + bundle XSS (GHSA-m23q-3295-mh2g, GHSA-xmgg-47vp-73xr); MetForm <4.3.1 webroot debug-file leak + REST submission-data read (GHSA-cr6m-q4jq-r64m, GHSA-5m3g-q793-wg8x); WP Ultimate CSV Importer <9.2 unsalted guessable import-log path (GHSA-w4w7-6vj3-3c3v) + archive-stored XSS via multisite unfiltered_html gap (GHSA-4qqx-23c4-hcqv); Mailchimp for WooCommerce <6.3 unauth abandoned-cart IDOR (missing-ownership, canonical); Photo Reviews for WooCommerce ≤1.2.30 arbitrary-post deletion via stored unowned attachment IDs + deferred wp_delete_post on admin/cron trigger (GHSA-24v8-rv6x-cqwg, deferred-consumer sibling noted above); Helpdesk for WooCommerce ≤2.1.6 ticket-response IDOR deletion via admin-footer nonce (GHSA-vv97-3hr9-5prm); Pie Register <3.8.4.14 invitation-code report username/email dump (GHSA-hj5m-8g2v-x4f9); Unlimited Elements search-value rewrite of prepared SQL (GHSA-f222-q2vh-g6q6, prepared-statement-post-edit, config-precondition-gated); AIOSEO ≤5.0.2 unauth arbitrary shortcode execution (GHSA-5q32-9w97-g3v9, do_shortcode canonical); ProfilePress ≤4.17.4 [pp-custom-html] shortcode-fragment profile-field disclosure via registration nickname/bio (GHSA-fc4p-8rjj-4hfw); EmbedPress unquoted-attribute block XSS (GHSA-2gcx-8mfj-5hvc); GD Rating System/Strong Testimonials/SEOPress/Welcart/Transliterator/Magic Tooltips/SaveTo/WP Ultimate Review/WPC Smart Quick View/EWWW/Real Cookie Banner/WPZOOM/LearnPress/Calculated Fields/XSS-class singles — generic sanitizer singles per precedent.

October 4 09:30Z follow-up: unscoped REST auth filter disables core nonce protection site-wide, rewrite-rule protection dead on multisite topology, and option-name resolver as disclosure oracle (Oct 4 09:30Z WP wave, folded)

  • CoCart ≤4.9.7 unscoped REST authentication filter → site-wide CSRF including admin creation (CVE-2026-93549 / GHSA-9p8w-fmwq-692f): the plugin registers a rest_authentication_errors-style filter that never checks whether the current route belongs to CoCart — when its own cookie-auth logic runs for every route, it causes WordPress core's REST nonce check to be skipped for all routes on the site, including core and WooCommerce admin routes. Result: a cross-site request from any visitor holding a logged-in administrator session can hit core POST /wp/v2/users and create a new administrator — the nonce wall that normally blocks state-changing cookie-auth REST requests is gone site-wide because of one plugin's laziness. Durable axes: (1) WP REST security is filter-stack security; an unscoped plugin filter modifies the security posture of routes it does not own — a single bad rest_authentication_errors/rest_pre_dispatch/rest_post_dispatch callback is a site-wide control change, so the audit question flips from "is this plugin's authz correct" to "which global filters are installed and what do they do to routes outside their namespace"; (2) for a bug hunter this is a multiplier discovery, not the finding itself: when any installed plugin registers an unscoped REST auth filter, every normally nonce-gated route on the site (core user creation, plugin settings routes, WooCommerce mutations) becomes plain CSRF — enumerate active plugins' REST filter registrations (add_filter('rest_authentication_errors' greps on open-source installs) and treat unscoped ones as a site-level authz finding independent of the plugin's own routes; (3) prove boundary: lab install with CoCart active, drive the admin-creation CSRF against your own lab from a second browser with an admin session, then delete the created account.
  • User Private Files <2.2.0 private-file disclosure because the protecting rewrite rule is never reached on multisite (CVE-2026-97332 / GHSA-rgr9-g879-r5wm): the plugin's access check lives in a rewrite rule that routes stored-private-file URLs through its PHP gate; on multisite installations the rule is never registered/reached, so direct file URLs return other users' private files with no authentication. Durable axis: a protection implemented as a routing-layer rule is topology-dependent — the same URL is gated on single-site and wide open on multisite/subdirectory networks, and vulnerability scanners and plugin authors both routinely test only the single-site shape. When a WP target is multisite (or uses alternate permalink/site-structure configurations), re-probe file paths protected by rewrite-based gating (private files, download gates, membership content gates) directly, and diff single-site vs multisite responses for the same canary path.
  • Five Star Business Profile and Schema <2.4.0 arbitrary option/meta read through unconstrained default-value resolver callbacks (CVE-2026-86817 / GHSA-qpw5-3rj5-433c): Author-level users can store schema-field default values that reference arbitrary callbacks/keys, and the resolver happily reads whatever name it is given — disclosing other users' password hashes and arbitrary wp_options values in public front-end output. Durable axis: name-to-value resolver callbacks are datastore-read oracles when the accepted name set isn't constrained — any feature where a low-privilege stored value later becomes an argument to get_option/get_user_meta/a callable name should be swept with well-known sensitive key names (*_keys, user meta containing hashes/tokens) on a disposable author account, and the public render checked for the canary value. Sibling of the coarse-permission secret-read class with the resolver-callback as the new input shape.
  • Same wave, tracked without publication on canonical axes: Razorpay for WooCommerce <4.8.8 unauthenticated checkout REST route modifying shipping info on arbitrary orders (GHSA-g56q-qwxf-x99w, missing-ownership canonical); Unlimited Elements ≤2.0.20 blind SQLi (GHSA-rcjh-9qxp-82pg, SQLi canonical); Simple Shopping Cart stored settings XSS, Horizontal scrolling announcements stored XSS, and generic XSS singles (GHSA-p57v-42f3-wfqr, GHSA-6g7j-p76q-h89g, plus three detail-thin 7.1 XSS entries) — sanitizer singles per precedent.
  • Same-wave non-WP tracked: InternLM MindSearch 0.1.0 planner-agent ExecutionAction.run code injection via inputs with public exploit (GHSA-4535-w5r2-pmqp / CVE-2026-105135, 10.0) — lands directly on the Oct 2 AI page's published "tool registry is the attack-surface map / enumerate all execution sinks, not just the obviously-named ones" rule; no new axis beyond it, vendor unresponsive. cognee ≤1.5.4 hardcoded FASTAPI_USERS_JWT_SECRET default signing key → forged auth tokens (GHSA-xrgh-2vxr-rhm4 / CVE-2026-105141) — shipped-default-secret class canonical on the Oct 2 AI page (Trigger.dev .env.example leg). Drogon ≤1.9.13/10.0-beta Windows StaticFileRouter traversal (GHSA-7fvc-r3q2-9v2h / CVE-2026-105144) — Windows backslash traversal class canonical. Laradock ≤20.4 workspace Dockerfile unsigned code download (GHSA-r2hw-g35f-pfw5 / CVE-2026-105137, high-complexity) — build-integrity class, no new sink.

  • Same wave, tracked without publication on this page's canonical axes: Ultimate Member ≤2.13.1 form_id stored XSS via submitted usermeta → admin Users-modal jQuery .html() (GHSA-6phc-8h2j-74hw / CVE-2026-96270, unauth front-door input / back-office sink, axis canonical); Beaver Builder ≤2.11.0.5 contributor blind SQLi via fields[][value] on get_autosuggest_values — the required fl_ajax_update nonce is emitted into the block editor for anyone who can edit a BB post, another author-capability-gated nonce mint (GHSA-27qq-rr92-q78g / CVE-2026-95865); SupportCandy ≤3.5.3 sort_by time-based SQLi behind compound Subscriber+agent-role precondition (GHSA-xqwv-9f36-ccgr / CVE-2026-94539) + name stored XSS gated on non-default config (GHSA-8cxj-g538-75wh / CVE-2026-94378); Ivory Search ≤5.5.18 highlight-term reflected XSS with admin-precondition (GHSA-fhf6-3c94-w2q4 / CVE-2026-92243); Jeg Kit ≤3.2.19 comment stored XSS via approved-email allowlist widening (GHSA-97rq-wvrr-p823 / CVE-2026-100180); Formbricks <5.4.4/<6.0.1 "Custom Head Scripts" survey feature enforced at readWrite instead of Manage → persisted script executes in every survey visitor's session (GHSA-q9hg-xqvp-x2xv / CVE-2026-105090 — role-gate drift on a feature that persists code executed in others' browsers; the shape duplicates the Trigger.dev/low-code config-as-code family, tracked). ThemeREX Addons ≤2.46.0 SSRF (GHSA-wx4c-58f5-rwc5, generic plugin-fetch class); Airano MCP Bridge ≤2.11.0 missing-authorization (GHSA-f55q-6qxf-8569, no-callback axis canonical); PublishPress user-controlled-key authz bypass (GHSA-jffr-vg9w-qc68); LearnPress missing-authorization sibling (GHSA-h3fr-24jq-9v5c); JetAppointment stored XSS (GHSA-fpfr-m3qm-9475); Aculect AI open redirect (GHSA-w4cx-23fp-xc39); Smart One sensitive-info-in-sent-data (GHSA-c299-27x5-pj33); HospitalManagementSystem/CodeAstro/SourceCodester/AVEZ thin-detail singles.

October 3 09:31Z wave tracked without publication

  • Beaver Builder ≤2.11.0.5 unauth arbitrary shortcode execution via Sidebar-module widget text (Recent Comments shape) with comment moderation off/approved (GHSA-jx8c-663q-ggc5 / CVE-2026-92084, critical) — do_shortcode on untrusted render chain is canonical here (AIOSEO sibling same day); the durable nugget is the render-chain precondition (attacker text must reach a widget inside a BB page) rather than a new sink.
  • VikAppointments ≤1.2.21 unauth arbitrary file deletion via extract() path validation gap, wp-config.php deletion → RCE path (GHSA-x82w-x82x-7998 / CVE-2026-87115, critical) — archive-extraction traversal class canonical (Unlimited Elements fallback leg above); wp-config-delete→reinstall is a known WP RCE tail. Precondition: published File-type custom field.
  • WP Visitor Statistics ≤8.7 second-order SQLi: unauth wmcTrack persists raw fullRef into wp_logVisit, admin Traffic Sources view triggers it (GHSA-f46r-g4h3-gxr2 / CVE-2026-96267) — deferred-SQL shape duplicate of the GeoDirectory leg promoted the same day; tracker-endpoint stored-header rule already covers the input side.
  • Smart Manager ≤8.97.0 subscriber SQLi via access_privileges where a role deny-list config that fails to block the internal access-privilege module implicitly permits subscribers (GHSA-c5cw-fc86-6h2j / CVE-2026-18443) — deny-list-default-allow + self-referential module gap noted; config-precondition-gated, sibling of Formbricks role-gate drift and SiYuan zero-check sweep.
  • WPCafe ≤3.0.18 contributor LFI via template-scope function (GHSA-qq8p-42q8-m7f5); Nelio Content ≤4.5.0 contributor deletes any nc_reusable_social post (GHSA-j2j8-hvh9-q6jf, sibling-action authz canonical); WP Mail Catcher ≤2.1.12 stored XSS via PHPMailer wp_mail_failed error text into mail-log view (GHSA-7wqp-vpcj-332m — error-message-as-user-data leg of the stored-input canary set, noted); Twenty20/WPFront/WPC Options/WPMobile/Responsive Plus/WP Ultimate Review pair/WPC Delivery Date/WPCafe enum singles — sanitizer/missing-cap singles per precedent.

October 7 09:30Z follow-up: capability-gated code-execution feature reachable by default Editor, and stored XSS whose final leg is the web server's MIME-sniffing default (Oct 7 09:30Z WP wave, folded)

  • WP Coder <4.5.2 Editor-role PHP code execution because the code-exec feature is gated on a content capability (CVE-2026-104677 / GHSA-pfgx-g476-6w3m): the plugin's "PHP code snippet" feature checks a capability the Editor role holds by default instead of an admin-only one, letting Editors save and execute arbitrary PHP on the server → full site compromise from a role handed to content teams and agencies. Durable axis: capability-choice drift, not capability-absence — the check exists and passes legitimately; the bug is picking edit_*/edit_theme_options-family capabilities for a code-execution sink. Sweep on every plugin that gates a powerful feature: read the current_user_can() argument and resolve it against the default role map (editors hold edit_pages, edit_theme_options, unfiltered_html in single-site) before assuming the gate is admin-only. Editor→RCE is the highest-severity WordPress finding class for agency-hosted estates; enumerate installed plugins with code/snippet/template executors (code-snippet managers, theme/ file editors, ad/tag managers) and test each from a disposable Editor account.
  • OMGF ≤6.3.10 stored XSS through the s search parameter in the comments-atom feed — with the delivery layer as the deciding leg (CVE-2026-89417 / GHSA-jmqx-vrvj-5m9h, high): the plugin's feed pipeline writes a retained .tmp file containing the unsanitized search term, and when the front-end server serves that .tmp without a Content-Type or X-Content-Type-Options header, MIME-sniffing browsers (Chromium) execute it as HTML — a condition the advisory notes is default on many Apache/nginx+php-fpm deployments. Durable axis: the stored-XSS chain's final sink can be the web server's default header behavior, not the app's escaping — when you find any persisted attacker content in a server-served path (temp/cache/export/feed files), test it fetched directly: no Content-Type, no nosniff, HTML-looking body = executing stored XSS even when the app never renders it. Add "list app-writable, URL-reachable file paths and diff response headers" to the stored-XSS sweep; the same posture catches cached-fragment and export-file XSS families.
  • Same wave, tracked without publication on canonical axes: Academy LMS <4.0.0 quiz-question and course-enrollment object-authz misses (GHSA-rg55-r6h3-vvf2, GHSA-43m9-7565-v53c, missing-ownership canonical); User Private Files <2.1.9 supplied-user-ID file access (sibling of the Oct 4 rewrite-gate leg, GHSA-m2gh-g9gw-hjhf); Nexi XPay Build ≤7.6.2 unauthenticated payment-result routes marking arbitrary orders paid/failed + order-key disclosure (GHSA-65w5-qcwh-f3g3 unverified-callback + GHSA-8fcj-x85r-h3ff token-validation leg; payment-state-machine family, callback-forgery shape canonical), Yaad Sarig gateway sibling (GHSA-6pp4-6q7m-6492); Optimole ≤4.2.15 missing capability check on an exposed function (GHSA-q3p9-mmwf-qgrc); If-So Dynamic Content ≤1.10.2 URL-scheme validation gap (GHSA-qp9g-v8qg-cx5q); Koinonia Link ≤1.1.5 unvalidated target-user change (GHSA-hx93-m334-hcgh); PowerPress <11.17.11, Envira pair, MetForm, Magee pair, String locator class-restriction, Animated Number Counters, WPCafe REST restriction miss, MPG import structure, Geliver cargo marketplace, Epos Now, Frontend Dashboard, CP Media Player — sanitizer/capability singles per precedent.

October 8 00:30Z follow-up: LatePoint subscriber IDOR where the contact-merge key decides whose password-reset email you redirect (CVE-2026-17538 / GHSA-gw8m-rqgv-6j3j, ≤5.6.9)

process_step_customer() gates on is_user_logged_in() alone before merging POSTed customer data (first/last name, email, phone, notes) into an existing LatePoint customer record — no ownership check. Any Subscriber can rewrite any customer's personal data, and when the site's contact_merge setting is phone, overwriting the email field on the victim's record makes the next password-reset send to your address → full account takeover.

  • Durable axis: merge-by-natural-key turns a plain field-write IDOR into identity binding. When a profile/customer store keys or merges records on a contact channel (phone, email, membership number) rather than an immutable ID, the field-write primitive crosses into authentication: the reset/OTP/2FA-SMS channel follows the edited field. Audit posture for every WP/custom booking, CRM, LMS, or member-portal plugin: find the record-merge/dedup logic, identify which field is the merge key under default settings, and test whether a low-privilege principal can write that field on a foreign record. The decision table is merge-key × write-permission × reset-channel — "subscriber writes victim's email under default merge setting" is the ATO finding, even though the advisory's base severity only says IDOR.
  • is_user_logged_in() is an authentication check masquerading as authorization — the WP canonical ("logged-in" is not "owns"), now with the merge-channel twist as the escalation leg. Disposable two-account harness (subscriber + victim customer with an owned-mailbox canary address); never touch real customer records.
  • Same wave, tracked without publication on canonical axes: Vault ACME/plugin-catalog/ACL four-pack was promoted on the Sept 20 credential-vault-platform page (Oct 8 follow-up) rather than duplicated here; Aurora Heatmap url stored XSS (GHSA-qg97-rqrx-gj82 / CVE-2026-94154) — sanitizer single per precedent.

October 8 06:31Z follow-up: backup-plugin trio where the trigger origin, the web-server topology, and the fallback archive library are each the boundary (BackWPup <5.7.7) + ABSPATH guard nullified by a trailing slash (Super Forms ≤6.3.316)

  • BackWPup <5.7.7 cron-handler trigger-origin spoofing (CVE-2026-86827 / GHSA-pcfw-vf4c-h2h5): the cron-triggered backup execution handler never verifies the request originates from WordPress's internal scheduled-event dispatch — unauthenticated attackers force any existing backup job to run immediately, off-schedule, repeatedly. Durable axis: scheduled-action endpoints must authenticate their dispatcher. Any WP route whose only guard is "this is normally hit by wp-cron" is unauthenticated if it's URL-reachable; enumerate cron-callback routes (add_action('wp_... / action hooks registered alongside wp_schedule_event) and test direct HTTP invocation. Job-forcing looks low-sev until you pair it with the next leg — repeated full backups of a large site are also an availability lever, and forcing a restore-window job changes the state machine under the admin's feet.
  • BackWPup <5.7.7 restore working directory web-reachable when the server ignores .htaccess (CVE-2026-86826 / GHSA-jprm-wgx9-37wq): protection is an .htaccess rule; on NGINX (and any server that doesn't honour .htaccess) the working directory is directly downloadable — the full backup archive (DB dump + site files, credentials and secret keys included) left behind by an interrupted restore. Durable axis, twin of the Oct 4 User Private Files multisite rewrite-rule leg: .htaccess-based protection is a topology-dependent control that silently fails-open on nginx — the plugin author tests Apache, the deployment runs nginx, nothing errors. WP-ecosystem audit rule: for every app-writable directory the plugin claims to protect with rewrite/.htaccess rules (backup dirs, restore staging, temp exports, cache), fetch a canary path directly and check whether the deny actually fires on the target's server software; interrupted-job leftovers (partial restores, half-written exports) are the content to look for. On nginx fronted by php-fpm there is often no deny at all — full-site credential disclosure from an interrupted restore is a common real-world shape.
  • BackWPup <5.7.7 fallback archive library escapes the restore directory (CVE-2026-86828 / GHSA-5547-r7f3-wccc, admin→RCE): when the plugin's fallback archive extraction path is used, the extracted file destination isn't confined — high-privileged users write files outside the restore dir. Axis: feature-flag/library fallbacks carry their own (weaker) validation — the primary ZipArchive path was checked, the fallback PclZip-style path wasn't. Sweep every "if library X unavailable, use Y" branch: the fallback is where path checks go missing (same one-canonical-form theme as the Vault ACL leg). Precondition is admin-level, so report as defense-in-depth/hardening-adjacent rather than primary RCE on default installs.
  • Super Forms ≤6.3.316 unauthenticated arbitrary directory deletion via ABSPATH guard defeated by dirname() trailing-slash normalization (CVE-2026-17609 / GHSA-pchj-gc42-gqq7, critical): the submit_form path validates attacker-controlled JSON field declarations insufficiently against the real form schema, and the containment check "path starts with ABSPATH" is trivially bypassed because a trailing slash makes dirname() strip it back out — recursive delete_dir reaches anywhere, including the WordPress root (precondition: admin enabled the non-default "delete files after submission" setting, which the advisory notes is common). Two durable axes: (1) containment checks that compare a path against a root constant break on normalization order — dirname($p) on $p = ABSPATH . '/../foo/' yields ABSPATH.'/../foo'→ parent: always test the trailing-separator and dirname-interaction variants of any prefix check, not just raw ../; (2) attacker-declared field schemas must be checked against the server's stored schema, not just well-formedness — when a submission accepts "field declarations" naming file paths, the schema is the validation boundary. wp-config-adjacent deletion is the WP reinstall-tail RCE path (VikAppointments precedent on this page).

October 9 09:31Z follow-up: Code Snippets <3.10.0 — "site administrator" capability is not network confinement, and snippet scope comes from the request (2 GHSAs, multisite topology)

The WordPress Code Snippets plugin (PHP-snippet execution as a feature — every snippet is code running network-wide) published two legs that complete this page's multisite topology theme (twin of the Oct 4 User Private Files rewrite-rule leg, this time in the authorization layer):

  • Network-scoped snippet activation controlled by a single-subsite admin (CVE-2026-106095 / GHSA-x27w-vpmw-g569): a snippet-management action skips the capability check and derives the network scope of the targeted snippet from the request instead of the stored record — a subsite Administrator (not a Super Admin) can activate, deactivate, and reprioritise snippets whose scope is network, i.e. code that runs on every site in the network. Axis: scope-selecting fields must be read from stored state, never from the caller, and on multisite an "activate a code snippet" verb whose scope is caller-declared converts subsite-admin into near-Super-Admin code execution (snippet content itself is limited by the plugin's own editor, but activation state + run-order is cross-site control; chain with any snippet-creation capability the subsite admin already holds for full network PHP execution).
  • UNION-based SQLi against shared network tables from a subsite admin (CVE-2026-106097 / GHSA-6xh4-5cg9-76mq): snippet-migration import endpoints are gated by "site-administration capabilities" — which multisite grants to subsite Administrators — and interpolate a user-supplied parameter into SQL, reaching shared network tables (wp_users, wp_blogs, wp_sitemeta): network-wide password-hash disclosure from a role the plugin author mentally modeled as single-site admin. Axis: manage_options-class caps mean "this subsite" to the author and "any subsite" to the attacker; import/migration endpoints are the least-audited verb family (this page's core invariant again — the import path enforces a different thing than the UI).

Durable multisite sweep rules for WP engagements: (1) determine topology first (wp-config WP_MULTISITE, wp_blogs shape via any SQLi, /wp-signup.php, path vs subdomain structure); (2) re-run every admin-gated plugin action from a subsite-admin account, not just subscriber/author — the subsite-admin↔Super-Admin boundary is systematically unmodeled in plugin code; (3) for every object with a scope field (network/site/blog ids), swap the scope value and diff — caller-selected scope is the bug; (4) import/migration/restore endpoints get their own probe pass. Validation boundary: lab multisite with your own subsite-admin + Super-Admin accounts, your own snippet rows and canary users; UNION proofs against your own tables only.

Same-wave tracked no-publish: Kirki <6.3.2 editor-gated SSRF host-check miss + comment-shortcode execution (known SSRF/shortcode classes, Sept 16 rmcp / Sept 19 shortcode pages), WP Rocket executable-regex + missing-auth singles, Redux Framework privilege escalation (class-covered), SendPress nonce-gated-no-capability pair, FooSales/UnitechPay/Social Web Suite/Ocean/AWP Classifieds/SKU Error Fixer singles (known broken-authz/XSS/archive-extraction classes), Linux kernel bpf/veth/netfilter wave (memory-safety, tracked per kernel precedent).

Four legs from this wave add genuinely new axes; the rest fold onto canonical classes listed at the end.

  • Blocksy Companion ≤2.1.58 unauthenticated seller/vendor self-registration + auto-login because the plugin actively disables another plugin's nonce guard and trusts $_POST['role'] (CVE-2026-107645 / GHSA-w5h9-m5j6-5394, critical 9.1): the implement_user_registration() AJAX handler runs add_filter('dokan_register_nonce_check', '__return_false') — killing Dokan's vendor-registration nonce from Blocksy's own code — then passes the attacker-supplied role straight into wc_create_new_customer() and wc_set_customer_auth_cookie(). Unauthenticated attackers mint a Dokan seller account (publishing capabilities beyond a customer) and are auto-authenticated into it, even on sites where Dokan vendor signup is explicitly turned off. Three durable axes: (1) cross-plugin filter injection as guard removal — when auditing a registration/checkout AJAX handler, grep for add_filter( calls that flip another plugin's *_nonce_check/*_enabled-style guard to false; the guard lives in the other plugin's code path, so the vendor who wrote the check never tested the site where a companion plugin disabled it; (2) client-supplied role at registration — any wc_create_new_customer()/wp_insert_user() call fed from $_POST['role'] is the bug regardless of how benign the created role sounds; enumerate the effective capability delta of each accepted role value (seller/vendor/author all clear "customer"); (3) feature-flag bypass via handler ordering — "signup disabled" is enforced in Dokan's form/dispatch, not inside wc_create_new_customer(); alternate entrypoints that call the shared creator function skip the posture check entirely (this page's alternate-surface invariant again). Sweep: on any Woo stack with a companion plugin that claims to "handle registration for X", probe the companion's endpoint with role= variants and diff created users + returned cookies; disposable sites only, enumerate your created accounts afterward.
  • WPO365 | Login ≤44.1 OIDC nonce replay through a validation primitive that can never succeed — and never aborts (CVE-2026-104759 / GHSA-p38j-g4g4-fm3g, high 8.1): the deprecated token parser validates a 64-char hex value produced by the plugin's own Nonce_Service::create_nonce() using WordPress core wp_verify_nonce() — which only accepts 10/24-char WP nonces, so verification always fails — and the failed result does not terminate execution: auth continues into authenticate_oidc_user() with the attacker-supplied id_token. Anyone holding a previously-issued valid id_token for a target account replays it to log in as that user, up to admin. Durable axes: (1) issuer/verifier format mismatch = fail-open validation — for every check that looks real in code, confirm the format the producer emits matches what the checker can accept; a check wired to a validator that structurally cannot return success is an absent check with a log line; (2) non-terminating validation failure — grep auth flows for if (wp_verify_nonce(...) || ...) and negated-continue shapes where a false result skips a branch instead of wp_die()/return; build the decision table {valid, wrong, wrong-format, absent} × {accepts, rejects, falls-through}; (3) deprecated parser behind an option — the leg is gated on use_id_token_parser_v2; when a plugin ships v1/v2 handlers, enumerate which option value routes to which, and fingerprint deployments by testing the broken-format leg (sibling of alternate-versioned-route families on the Keycloak page). Same plugin, same wave: stored XSS via the wpo365_errors transient (CVE-2026-96765 / GHSA-87pp-p526-6wm7, 7.2) — a forged id_token whose base64url-decoded unique_name/iss claim contains HTML is stored unauthenticated in a 3-day transient and rendered on the admin wizard page. Axis: JWT claims are attacker-controlled strings that plugins happily persist as "error context" — run the mXSS/DOM marker battery through every claim value, then hunt where error transients/options survive to admin-rendered pages; unauthenticated → admin-sink stored XSS needs zero user interaction beyond an admin opening the settings page.
  • WPCOM Member ≤1.7.27 full auth bypass by writing attacker-named entries into another visitor's session namespace (CVE-2026-104803 / GHSA-gj32-ffvm-frj6, critical 9.8): the social-login callback on init has no nonce, no OAuth state verification, and no per-visitor isolation — a crafted GET writes an attacker-named/attacker-valued entry into the global session store by prepending an underscore to bypass the per-visitor prefix, a second GET fires weapp_new_user() which reads the forged entry and resolves the attacker-supplied openid to the bound WordPress account, and wp_set_auth_cookie() logs the attacker in as that user (admin included) if the victim's openid/unionid is known or enumerable. Durable axes: (1) session-store key namespace is an authorization boundary — any handler that writes session/option/transient entries with caller-influenced keys must confine keys to the caller's own prefix; test the underscore/global-escape, empty-prefix, and case variants; (2) two-request handshake attacks — social-login flows decompose into "store claim" + "consume claim" legs; each leg is individually reachable via GET (this page's GET-state-change invariant), and the consumer leg trusting the store is the whole bug; (3) provider identifier as credential — openid/unionid values minted by a shared provider (WeChat unionid is stable across every app of the same Open Platform account) can leak across ecosystems, so "requires knowing the victim's openid" is weaker than it reads; enumerate provider docs for identifier scope before accepting the advisory's precondition. Sweep: every social-login plugin's callback handler — check state/nonce presence, then probe the store/consume split with your own two disposable bound accounts.
  • Download Manager ≤3.3.71 suspension email compiled inside the admin's own request leaks the full Cookie header (session hijack) (CVE-2026-104735 / GHSA-qj64-pjpc-4f52): an admin clicking Suspend on the attacker's account causes the plugin to synchronously build and send the suspension email inside the admin's authenticated HTTP request, and the email template has access to the request's raw Cookie header including wordpress_logged_in_* — delivered to the (attacker-controlled) suspended user's mailbox. Durable axis: admin-action-triggered emails are a request-context side channel — transactional emails generated synchronously during privileged requests can inherit request data (cookies, headers, signed URLs, TOTP material) as template variables; map every admin action that emails the subject user, and diff what the email body/headers actually contain against what the admin typed; the attacker picks the mailbox. The CVSS 4.3 undersells the outcome (full session hijack). Same plugin, same wave: stored XSS via regurl that fires only for logged-out visitors (CVE-2026-102401 / GHSA-mw8v-g8v9-8mxj) because the vulnerable template branch is gated !is_user_logged_in() — remember to verify stored-XSS payloads from both auth states; template-branch parity means the same stored payload has different victim populations than the tester assumes (your logged-in browser will show nothing).
  • Extensions For CF7 ≤3.4.5 unauthenticated arbitrary file upload: sanitize_file_name() reconstitutes the blocked extension (CVE-2026-94589 / GHSA-fjhx-3cm7-whvf, critical 9.8): the signature field's validation_filter() does no extension/MIME/size validation, the upload directory has no PHP-execution guard, and shell.php- survives validation because sanitize_file_name() strips the trailing - back to shell.php. Durable axis: sanitizers that delete characters can create the blocked string — for every deny-list extension check, test inputs where validation sees string A and the filesystem sees sanitize(A): trailing/interior banned chars, double extensions, %-entities, and separator swaps; always re-read what wp_handle_upload() actually stored, not what the filter rejected. Pair with the Oct 7 OMGF leg (server-layer decides executability).
  • Divi Plus ≤2.4.0 unauth arbitrary file read + SSRF via a REST endpoint whose permission_callback returns true unconditionally (CVE-2026-91136 / GHSA-9676-xmxf-xp84, high 7.5): /wp-json/elicus/v1/dipl-modules/svg-animator pipes svg_image into file_get_contents() (so file:// stream wrappers work) with a wp_remote_get() fallback (so the same parameter is also an SSRF dial), and the raw body is reflected in the JSON html field. Axes: __return_true permission callbacks remain the top REST sweep target (enumerate register_rest_route sites and read the callback, don't fuzz the gate); sanitize_text_field()/esc_html() are not path controls — the escaping target and the sink target are different layers (Sept 19's validation-target-vs-write-target rule); one parameter crossing both file_get_contents and the HTTP client is a two-bug finding — report both legs. LatePoint ≤5.7.3 latent admin-mint via settings write (CVE-2026-104766 / GHSA-h977-fppf-xgg7): a settings__edit-capable agent role can persist default_wp_role_for_customer = administrator because the role allowlist exists only in the UI dropdown — every subsequently self-registered customer is created as a WordPress admin. Axis: settings writes whose only allowlist is a <select>, and config-bombs: a setting that governs future account creation converts a low-priv settings write into standing privilege escalation; for every plugin with "default role for new X" settings, attempt the admin value via raw POST even when the dropdown forbids it (LatePoint is the second promoted leg on this page — same-product re-sweep rule). WebToffee PDF Invoices ≤5.0.2 guest document IDOR authorized by base64(billing email) (CVE-2026-93746 / GHSA-wjmp-g49r-xp3p): the guest print handler accepts an order's documents when the attacker-supplied base64url email equals the order's billing email — a non-secret identifier used as the authorization check where WooCommerce's order_key exists for exactly this purpose. Axis: encoding is not a capability — grep handlers for authorization by equality against user-attacker-known attributes (email, phone, username) instead of issued secrets; base64/URL-encoding of the compare value is cosmetic. W3 Total Cache <2.10.6 deferred-import confused deputy (CVE-2026-107321 / GHSA-445r-vc94-h34g): an Author plants a media-import entry pointing at an arbitrary server-readable file; the file copy runs with the admin's privileges when the admin later runs the import, landing the file in a publicly served directory. Axis: deferred-action queues inherit the consumer's authority, not the enqueuer's — every "admin clicks import/process/export on data a lower role wrote" flow is a read primitive across the role boundary (same deferred-detonation shape as the Brocade config-relay and GeoDirectory trigger legs); enumerate import/queue tables for author-writable rows and watch what the admin run actually copies.
  • Same waves, tracked without publication on canonical axes: ~20-leg ThemeREX/Axiomthemes PHP object-injection 9.8 dump (Booklovers/Gutentype/Tantra/Convex/Greeny/Travesia/Partiso/Smash/IPharm/Dwell/Rosalinda/Hygia/Camelia/Edema/Hogwords/Smart Casa/Let's Play/Veto/Balance — one shared theme-framework sink advertised under dozens of slugs; vendor-family fingerprint rule: one ThemeREX deserialization sink = sweep all sibling slugs from a single harness; detail-free vuldb bodies, no new axis); WPCOM/WPO365 sibling XSS singles; WP File Download ≤6.3.9 subscriber delete/move/publish across managed files (GHSA-cqx4-48wp-q2rc missing-action-check canonical); Fluent Forms ≤6.2.5 custom-role submission read/delete/settings (GHSA-pmcp-c5j9-q942 same UI-role-vs-server-role shape as LatePoint, class-covered); Booking Package <1.7.30 unauth reservation disclosure + cancellation tokens (GHSA-hhf8-8xcf-35xv IDOR + capability-carrier canonical); Grocery Shopping Store ≤1.3.3 password-recovery alternate-path bypass (GHSA-ghj7-cmq3-785j detail-free); LatePoint ≤5.7.2 booking[service_id] SQLi (GHSA-mwwp-rchw-pr78 generic SQLi canonical); Motors ≤1.4.108 missing-authorization single; W3TC/ContGallery/W3-pair rate-limit singles; ZTE Z80 Ultra pack (local Android info-disclosure singles); ExifTool-for-Android shell-string build from unescaped single-quote in media path (GHSA-fwcv-c88q-m2pm shell-quote page class); Groundhogg pair, Feedzy, GeoDirectory, Filter Everything, Hello Plus, Post Export Import traversal, Academy LMS pair, CleanTalk, FireBox, FV Flowplayer, Bookly trio, Table Field ACF, Avada, HivePress, Retainful, VikBooking, Photo Reviews, LazyLoad, PostX, User Frontend, FunnelKit, QSM, Molongui, SiteOrigin traversal, 10Web Booster, WP Meteor, Premium Packages, Kirki re-listing, Divi Plus singles (stored/reflected XSS, enum, IDOR singles per precedent).

October 14 03:30Z follow-up: standalone-file bootstrap bypass (Snazzy Social Media Feed), per-branch allowlist divergence with anonymously-minted nonce (Printcart Store), and log-re-execution inside the admin's session (Bit integrations) (Oct 14 WP wave)

  • Snazzy Social Media Feed ≤2.5 unauthenticated arbitrary file upload → RCE (CVE-2026-110002 / GHSA-cqr7-6967-pf9v, critical 9.8): save-to-cache.php is a standalone script in the plugin directory that never loads WordPress — no bootstrap, no auth, no capability, no nonce — and writes the pluginURL parameter into cached-content/cached-feed.php with only FILTER_SANITIZE_URL applied, a filter that preserves every character needed for PHP source. Subscriber-equivalent (really: anonymous, the advisory's auth bar is fiction since the file is directly reachable) writes executable PHP to a web-served path, one GET to execute. Durable axes: (1) the standalone-file sweep is this page's core invariant restated as a grep — find wp-content/plugins/<x> -name '*.php' and test each one that doesn't require wp-load/ABSPATH-guard: any directly-reachable non-bootstrapped PHP file skips all of WP's auth model at once (siblings: the wiki's uninstall.php and *-ajax.php handler hunts); fuzz the reachable-file set, not just admin-ajax.php/wp-json; (2) sanitizers chosen for a different purpose are not security controls — a URL sanitizer applied to content destined for a .php file is a category error; check the destination's execution semantics against the surviving character set.
  • Printcart Store (PCDesigner/NB Designer) ≤2.9.1 unauthenticated upload RCE via allowlist branch divergence + free nonce (CVE-2026-93388 / GHSA-p5c5-938c-g6r5, critical 9.8): nbdesigner_copy_image_from_url is registered wp_ajax_nopriv_; the normal branch enforces a jpg/png/gif allowlist, but the Google Drive branch rebuilds the destination filename from raw gapi[name] — extension fully attacker-controlled — and writes fetched bytes to wp-content/uploads/nbdesigner/temp/; the required save-design nonce is handed to anonymous callers by a different endpoint (nbd_check_use_logged_in). Axes: (1) per-branch validation parity — when one handler has two content-source branches (direct upload vs remote fetch vs provider import), diff the validation applied by each; the imported/remote branch is almost always the lax one (same rule as the Oct 8 SAN data-collector and Crawlee legs); (2) nonce-mint sibling endpoint — Bricksforge's regenerate_nonce pattern generalized: before accepting a nonce gate, enumerate every response on the site (including logged-out pages and cheap AJAX actions) that embeds the target nonce action name; (3) filename-from-provider-metadata is filename-from-attacker — provider metadata fields are client-side data.
  • Bit integrations (btcpay-form suite) ≤2.10.6 privilege escalation via log re-execution (CVE-2026-104749 / GHSA-8mmw-9hhm-8rr4, high 7.5): executeWithCapture() stores raw anonymous form fields — including user_pass — verbatim into wp_btcbi_log, and the admin-facing LogHandler::reexecute() replays the stored payload through Flow::execute() inside the replaying administrator's session, so updateUser() resolves the target to the admin and writes the attacker's password → unauth admin ATO, gated only on an admin clicking "Re-execute" on the failure row the attacker provoked. Axis: deferred-execution queues where the replayer's identity authorizes the enqueuer's payload — the third deferred-detonation leg this week (W3TC import, ONLYOFFICE runtime.json, this) and the WP-admin-panel flavor: every "retry/re-execute/replay" button over a log table an admin reviews is a payload-delivery channel from unauthenticated input; audit whether replay re-resolves the acting principal or inherits the viewer's. Report precondition honestly: requires a configured flow mapping a form field to user_pass.
  • Automatic Role Changer ≤20260828 revoked-admin resurrection (CVE-2026-104767 / GHSA-m963-j4qw-ph48, high 7.5): remember_foreign_roles() merges externally-granted roles into a user-meta cache but never evicts revoked ones, and maybe_add_role_to_user() unconditionally re-assigns every cached role on any role event → a subscriber who once legitimately held Administrator re-grants it to themselves by buying a role-mapped product. Axis: derived/permission-caching layers that only ever ADD — the MISP stale-correlation-snapshot and SmarterMail stale-role-refresh revocation-gap class applied to an identity mirror cache; revocation tests must cover: revoke upstream → trigger every downstream sync event → check re-grant. Preconditions (Replace Roles mode + prior legitimate admin) stated honestly; still a durable audit pattern for any SSO/HR-sync role bridge.
  • Tracked this wave without publication: Directorist ≤8.10.2.1 subscriber cross-owner listing delete via wp_localize_script-exposed nonces (public-nonce class, Booking Package ≤1.7.29 PII dump same-class — both canonical nonce≠authorization); BP Profile Search ≤5.9 LFI via bps_directory cookie → bp_locate_template() with no basename check and a HTTP_REFERER-derived gate (referer-as-authorization canonical; cookie→template-path = known cookie-input-sink class); CFDB7 ≤1.4.1 unauth arbitrary unlink() via any stored field name containing cfdb7_file (substring-key-match deletion — substring-matching as authorization scoping worth watching, single leg); AnyComment ≤0.3.6 stored XSS via subscribe REST endpoint rendered when user_ID fails to resolve (conditional-render XSS canonical). Non-WP tracked: TeamPlus Messenger JS-injection→code-exec pair (Zellic, client-app warning-click chain, known class), Kasa local-protocol unauth management (IoT adjacent-network canonical), Hyland Desktop Host %PROGRAMDATA% weak-service-path LPE (canonical unquoted/weak-permission service dir), Hitachi disk-array driver trio (vendor boilerplate), Samsung QA-Board cmdi (detail-free), Unreal Engine LaunchURL empty-scheme-filter promoted on the Oct 14 document-server page.

October 14 06:31Z follow-up: decorative capability arguments on a non-bootstrapped standalone admin.php (AGE-GATE) and empty-string credential accepted as authenticated (JTL-Connector) (Oct 14 WP wave)

  • AGE-GATE ≤1.0 unauthenticated RCE (CVE-2026-104800 / GHSA-rh8j-h273-hvj3, critical 9.8): the plugin ships its own standalone admin.php that never loads WordPress and carries no ABSPATH guard — the "decorative capability arguments registered via the plugin's simulated menu API" are fiction; POST width/height land unsanitized in generated PHP source written to an included file. This is the second same-day instance of the Snazzy save-to-cache.php axis (03:30Z wave above): the standalone-file sweep is now a two-for-one on a four-hour window — enumerate every directly-reachable plugin PHP file that doesn't bootstrap WP, and treat any capability/menu registration claimed by such a file as unverified UI theater. Extension of that entry: AGE-GATE's file is literally named admin.php inside the plugin directory, so path guessing via plugin README/zip listing (unauthenticated source is public) enumerates these endpoints pre-auth.
  • JTL-Connector for WooCommerce ≤2.4.3 arbitrary file upload → RCE (CVE-2026-87855 / GHSA-7mjr-phqx-8hgq, critical 9.8) + same-plugin time-based SQLi (CVE-2026-78193 / GHSA-38p9-rj5h-7qh4, high): startSession() accepts an empty jtlauth parameter as a valid credential, unlocking saveImage()/handleImagePush() with insufficient file-type validation. Axis: empty-string-as-credential — the Oct 4 phpMyFAQ empty-default-API-token and hMailServer classes generalized from "default secret" to "absence of secret parses as success"; fuzz every auth-parameter gate with '', missing, and null before theorizing about the crypto. Same product carrying two critical/high legs = second JTL sweep precedent for the same-product re-sweep rule.
  • Tracked this wave without publication: the remaining Oct 14 06:31Z WP batch is sparse vuldb-style singles already class-covered on this page (Form Maker/Gmedia/Hyyan SQLi, NewStatPress/FV/Enfold/Countdown/PO-MO/Verified Reviews stored XSS, Avada info-exposure, Tutor LMS, Directorist re-listing).

October 14 09:31Z follow-up: unauth admin self-registration through a meta exclusion list that omits wp_capabilities (SimpleForm) and the page-gate token printed on the page it gates (WP Data Access pair) (Oct 14 WP wave)

  • SimpleForm – Form Maker ≤3.10.0 unauthenticated Administrator creation (CVE-2026-104748 / GHSA-5hqh-jvjf-mpvw, critical 9.8): wp_ajax_nopriv_simpleform_wp_register has no capability check on role assignment, save_custom_fields_to_user_meta() protects user meta with an exclusion list that omits wp_capabilities, get_form_settings() returns hard-coded defaults that unconditionally enable meta writing regardless of the supplied form_id, and the required nonce is emitted into the front_end_data JS object on every front-end page. Payload = standard registration fields + wp_capabilities[administrator]=1. Durable axes: (1) deny-lists over wp_usermeta keys are a losing game — wp_capabilities must be explicitly protected, and every registration/profile-save form that writes arbitrary submitted keys to user meta inherits this hole; probe rule: for any form-to-user-meta writer, submit wp_capabilities[administrator]=1 (URL-encoded array syntax) and check the resulting user object; the add-only-role-cache page leg and the Oct 13 role self-grant legs are the cache flavor, this is the raw-meta flavor; (2) hard-coded defaults that fail open on unknown identifiers — passing a bogus form_id should reject, but here it selects the "meta writing ON" default: the absent/unknown-input-selects-permissive-branch battery (SPIP absent-param, Enswitch absent-parameter) applied to a settings lookup; (3) the public-nonce class fires again — a nonce embedded via wp_localize_script is free, so pair-nonce-gate every wp_ajax_nopriv_* registration handler as if ungated.
  • WP Data Access two-leg authorization-drift pair: export-token-is-public — the database-table export action is gated only by a token the plugin itself prints into the public page displaying the table, letting unauthenticated callers export complete table contents including columns and rows withheld from the rendered display (CVE-2026-106099 / GHSA-mjx7-qq55-q3w6); and read-gate-on-write-verb — one application REST endpoint verifies only read permission before performing a write, so anonymous read-exposed applications accept updates even when the admin disabled update actions (CVE-2026-106098 / GHSA-v8fc-v39p-fp8c). Axes: (1) a gate credential displayed by the gated UI is not a gate — before treating any page-embedded token (export tokens, edit tokens, preview keys) as an access control, check whether your current unauthenticated response already contains it (same root family as the public-nonce and wp_localize_script exposures — the renderer leaks the capability it's about to check); the row/column-masking angle means the export verb must be tested for field-level parity with the render, not just row parity; (2) verb-gate drift on public data-application endpoints — this page's Payload/ESO read-vs-write rule again: enumerate each HTTP verb on anonymous-readable data-app routes and diff which permission each checks; the read path being open makes the write path look intended.
  • Tracked this wave without publication: the rest of the 09:31Z WP batch is sparse vuldb-style singles class-covered here (LifterLMS/GeoDirectory/Mang Board/Complianz XSS-LFI singles tracked on their class pages, LatePoint legs folded on the pretix placeholder page this run); Sunshine Photo Cart ≤3.7.4 comment write into restricted galleries while the display path checks access (CVE-2026-108069 — display-gate/write-gate asymmetry noted, thin single); CodeAtoZ B2B guest-quote enumerable-ID reads (guest-ID sweep canonical); File Upload to Order unauth arbitrary unlink() via session-derived path (unauth file-delete class); Restricted Site Access missing-authorization sparse single; Koha legs folded on the query-grammar page and shell-quote page this run. Non-WP tracked: curl HTTP/2 RST_STREAM upload client-side UAF CVE-2026-92392 (client library, watch for client-target angle), unnamed critical T-SQL body-parameter SQLi CVE-2026-89310 (9.9) and "Vulnerability in tbc" CVE-2026-89309 (10.0 boilerplate, no product identified — revisit on enrichment), unnamed invoicing-PDF missing-authz + search-engine-indexed paths CVE-2026-14851 (product unnamed; the indexed-invoice-path recon axis is already page canon), Trellix Agent 5.8.4 hardcoded key in mfecryptc.dll → local DB decryption (local detail-free), EC-CUBE AmazonPay order-flow open redirect (known redirect class), HPE NonStop iTP WebServer memory corruption (detail-free), Tronclass grading-anonymity IDOR pair (privacy-restore IDOR class).

October 14 11:1xZ follow-up: universal route_call AJAX dispatcher exposes internal handlers as anonymous IDOR verbs (LatePoint) (Oct 14 WP wave)

  • LatePoint ≤5.7.3 unauthenticated booking/cart IDOR (CVE-2026-103366 / GHSA-3pf7-5297-2ffv, high): the public wp_ajax_nopriv_latepoint_route_call dispatcher routes to internal helpers by name, and steps__reload_booking_form_summary_panel/steps__start feed raw booking[id]/cart[id] into set_booking_object()/set_cart_object() → OsModel::set_data() loads an arbitrary row by primary key with no ownership check — the ownership guard the vendor added after the earlier disclosure was placed at one entry point, not at the model loader the dispatcher shares. Axes: (1) generic route-dispatcher AJAX endpoints multiply the audit surface — one nopriv action that names internal routes means every internal step-helper is a candidate public verb; enumerate dispatcher route names from plugin JS/source and probe each for object-ID parameters; (2) per-entry-point ownership guards fail on the shared loader — when a vendor patches "the disclosed endpoint," test sibling dispatcher routes that reach the same set_data()-style loader; the patched-twin differential applies to route families, not just CVE twins. LatePoint auth-bypass leg from the same wave folded on the auth-precedence page; placeholder-expansion legs remain canonical on the pretix page.