Authenticated SQL Injection in WooCommerce Order Export
Reported with a proof of concept, confirmed by the developer, and patched with esc_sql() — all inside 24 hours. A case study in how fast coordinated disclosure can move.
Product
WooCommerce Order Export (WordPress plugin)
Class
CWE-89 — SQL injection
Auth required
Yes — authenticated session
Status
Confirmed & Patched — esc_sql() applied
CVE
Requested — pending
Reported
Mon Oct 05 2026 00:00:00 GMT+0000 (Coordinated Universal Time)
Updated
Tue Oct 06 2026 00:00:00 GMT+0000 (Coordinated Universal Time)
01/Summary
During a routine security assessment of a WordPress e-commerce stack, I discovered an authenticated SQL injection vulnerability in the WooCommerce Order Export plugin. User-controlled input was incorporated into SQL statements without adequate sanitization or parameterization, allowing an authenticated user to manipulate the structure of the underlying query. I reported the issue to the developer, Alex Prokaev, on October 5, 2026, together with a working proof of concept, and received a response within hours.
The developer promptly confirmed the vulnerability and shipped a patched build that applies esc_sql() escaping to the affected input. The turnaround from initial report to a working fix was under 24 hours — a strong example of how effective coordinated disclosure can be when maintainers are responsive. A CVE identifier has been requested, and this page will be updated the moment it is assigned.
02/Vulnerability Details
| Field | Detail |
|---|---|
| Product | WooCommerce Order Export (WordPress plugin) |
| Vulnerability class | SQL Injection — CWE-89 |
| Authentication | Required (authenticated session) |
| Root cause | Insufficient sanitization of user-controlled input used in SQL query construction |
| Fix | esc_sql() escaping applied to the affected input paths |
| CVE | Requested — pending assignment |
A notable aspect of this case is the remediation approach. The plugin intentionally supports arbitrary custom fields, which means the set of valid column identifiers is dynamic by design — a static allow-list would have broken legitimate functionality. The developer instead routed user-supplied values through WordPress's esc_sql() API, which escapes characters commonly used in SQL injection payloads while preserving the plugin's flexibility. For this class of dynamic-input scenario it is a reasonable, pragmatic fix.
03/Impact
Successful exploitation allows an authenticated attacker to interfere with the SQL queries the plugin executes. Depending on the privileges of the database user configured for the WordPress installation, this could enable reading sensitive data — customer records, order details, and anything else reachable by the application's database account — and in worst-case configurations, modifying or deleting data.
The practical risk is highest on multi-user WordPress installations such as marketplaces, membership sites, and agency-managed stores, where lower-trust accounts exist by design. Sites operated exclusively by trusted administrators present a smaller attack surface, but the issue should still be treated as serious: SQL injection is a classic escalation path from a low-privileged foothold to full database compromise.
04/Disclosure Log
[2026-10-05]
Initial report
Vulnerability identified through manual testing. Report with an authenticated proof of concept sent to the plugin developer.
[2026-10-06]
Vendor confirmation & patch
Developer confirmed the issue and delivered a patched build applying esc_sql() to the affected code.
[2026-10-06]
CVE requested
CVE identifier requested. Writeup published with full technical details embargoed until assignment.
[Pending]
CVE assignment
This page will be updated with the identifier as soon as it is assigned.
[Pending]
Public patch release
Patched version published through the plugin's official public distribution channel.
05/Vendor response
The developer's reply arrived within roughly 24 hours of the report. He confirmed the vulnerability and shipped a patched build that routes the affected input through esc_sql(). A static allow-list was ruled out, he explained, because the plugin deliberately supports arbitrary custom fields — hard-coding the set of valid column names would break legitimate exports. Private correspondence, so this is paraphrased rather than quoted — the substance is his; the wording is not.
This is exactly how coordinated disclosure should work: a concise report from the researcher, a fast acknowledgement from the maintainer, and a working fix shipped the next morning. The developer also kindly offered to credit this website in the plugin's readme, which is appreciated — public credit is one of the things that keeps independent research sustainable.
PATCH/Patch available — update your store
06/Lessons for developers
esc_sql() escapes user input for safe inclusion in queries, but wherever possible parameterized queries through $wpdb->prepare() remain the stronger default, because they structurally separate code from data instead of relying on escaping. Dynamic identifiers such as column names cannot be parameterized, so they deserve explicit validation even when the set of valid values must stay flexible.
For plugins that must accept arbitrary field names, a dynamically-built allow-list — field names enumerated from the actual schema or registered field definitions — combined with escaping for the values provides defence in depth. None of this diminishes the quality of the response here: report to working patch in under a day is genuinely fast.
WARNING/Technical details embargoed