Skip to content

Array-valued AJAX action causes strpos() TypeError #1147

Description

@pirate-bot

Summary

A logged-out AJAX request whose action parameter is submitted as an array can cause Optimole to terminate with a strpos() TypeError during startup.

Expected behavior: the request is handled or rejected without an Optimole fatal error.

Actual behavior: Optimole passes the array value to strpos(), producing a fatal error before the request completes.

Impact: affected frontend AJAX requests fail with a 500 response while Optimole is enabled and connected.

Customer context

  • Product / area: Optimole WordPress plugin, AJAX request detection
  • Version: 4.2.12
  • Environment: WordPress 7.1, PHP 8.3.33
  • Integration / third party: Not provided
  • Reported error / symptom: strpos(): Argument #1 ($haystack) must be of type string, array given
  • Impact: 20 telemetry occurrences across 2 production sites between 2026-09-12 08:35 and 15:01 UTC.

Reproduction notes

Reported production context: frontend requests on Optimole 4.2.12, WordPress 7.1, and PHP 8.3.33.

  1. Enable and connect Optimole.
  2. Send a logged-out AJAX request with an array-valued action parameter, such as action[]=wpmdb.
  3. During Optimole startup, the request reaches AJAX detection and the reported strpos() TypeError occurs.

Direct PHP evaluation of the reported expression with an array argument produced the same TypeError. A full WordPress request reproduction was not run.

Diagnosis

Conclusion

Production telemetry identifies a TypeError at Optml_Manager::is_ajax_request(). The inspected v4.2.12 source passes $_REQUEST['action'] directly to strpos() after only checking that the key exists. PHP represents action[]=wpmdb as an array, which matches the reported argument type and produces the fatal on PHP 8.3.

Where this likely occurs

  • Frontend AJAX startup path in inc/manager.phpOptml_Manager::should_replace() lines 296-370 calls Optml_Manager::is_ajax_request() at lines 309-311.
  • inc/manager.phpOptml_Manager::is_ajax_request() lines 377-401 reaches strpos( $_REQUEST['action'], 'wpmdb' ) at line 396 without a scalar-type check.
  • The call is reachable for logged-out AJAX requests: inc/manager.phpOptml_Manager::is_ajax_request() lines 382-400 returns before this expression only when the user is logged in, AJAX is unavailable, or the request is not AJAX.
  • The expression exists in release tag v4.2.12 (ce4220e93d2a9cf83aa4351540df4e9255d028f3). Git blame attributes the line to 02df07746 from 2019; no earlier working release boundary was established.

Engineering notes

  • The confirmed path is limited to AJAX requests while the visitor is logged out and Optimole is connected and enabled; these are the observed guards in the inspected code.
  • A request such as action[]=wpmdb is a plausible trigger because PHP converts bracketed request keys into arrays. WordPress core behavior after plugin initialization was not inspected locally; the telemetry and code order establish that Optimole evaluates this parameter during startup.
  • This is distinct from the four file/class loading crashes in the same telemetry batch. Those traces were assessed independently and are not represented by this entry.

Test coverage status

phpunit.xml registers the tests/ PHPUnit suite. No relevant coverage was found during inspection for Optml_Manager::is_ajax_request(), an array-valued $_REQUEST['action'], or the wpmdb exclusion. tests/test-cache-header.php is manager-adjacent but covers unrelated cache-header behavior.

What to verify or explore next

  • May be worth reproducing against a WordPress AJAX request with action[]=wpmdb on supported PHP versions.
  • May be worth running the PHPUnit suite and checking whether request-shape coverage exists outside the inspected tests/ paths.
  • May be worth confirming behavior with non-wpmdb array action values and with logged-in versus logged-out requests.

Unknowns / follow-up

  • Telemetry does not retain the original request payload, so the exact submitted array shape is unavailable.
  • No precise open GitHub issue was found through repository issue search.

Confidence

Confidence: 97/100

v4.2.12 passes an array-capable $_REQUEST['action'] value directly to strpos() on a reachable logged-out AJAX path, matching the production TypeError. The other four crashes reference files or an SDK class present and mapped in the inspected v4.2.11 source, so the available evidence favors incomplete or mixed deployments rather than repository defects.

Crash telemetry

Occurrences 20
Distinct sites 2
First seen 2026-09-12 08:35 UTC
Last seen 2026-09-12 15:01 UTC
Crash location product:inc/manager.php:396
Request context frontend
Inside Themeisle SDK no
Product versions 4.2.12
WP versions 7.1
PHP versions 8.3.33
SDK versions 3.3.61

Source: automated crash report — optimole-wp, fingerprint dc1c56b497c01bc567b15f51e34401fc
Generated by bug-report-triage (ID: bug-report-triage_6aa63c5159bf59.34701292)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions