Introduction
An unauthenticated visitor to a WordPress site running Amelia Pro 9.9.1 or earlier can inject SQL into an events query just by choosing the names of the array keys in a tag parameter. No account or user interaction is needed, and the result is time-based extraction of database contents, so a public booking calendar becomes a read path into the site's database.
Amelia is a WordPress booking automation product for service businesses, covering appointments, employees, locations, customer management, booking calendars, automated notifications, events, WooCommerce integration, and Google Calendar synchronization. It is built by TMS, now Melograno Venture Studio, which Alexander Gilmanov founded in Belgrade, Serbia, in 2014, and the free directory edition reports 90,000+ active installations on WordPress.org. That figure covers the free plugin rather than the commercial Pro edition affected here, so it indicates ecosystem relevance, not the number of vulnerable sites.
Wordfence, acting as the CNA, scores CVE-2026-116751 at CVSS 3.1 7.5 (High):
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
That is network reachable, low complexity, no privileges, no user interaction, unchanged scope, and high confidentiality impact, with no scored integrity or availability impact. The score belongs to Wordfence; NVD displays its own assessment as unavailable. The weakness is classified as CWE 89 (SQL injection), and Wordfence credits researcher leon figueira of elitor.ai.
Technical Information
Root cause: values are escaped, keys are not
WordPress runs request superglobals through wp_magic_quotes, which escapes the values of request arrays but not their keys. Most SQL injection reviews focus on values, so a parameter like tag[] looks safe when its values are quoted. In Amelia Pro, though, the keys of the tag array are used to build SQL placeholder names. According to the NVD description, attacker-controlled tag[] keys reach EventRepository::getFilteredIds() completely unescaped and can be crafted to defeat the plugin's Statement::execute placeholder binder via overlapping strtr() substitution keys.
That is the distinction that matters. The attacker is not just supplying an unquoted value, they are influencing the text used to construct the query's placeholder names, which then drive substitution into the SQL statement.
How tag keys become placeholder names
The advisory references code in the free ameliabooking trunk on plugins.trac.wordpress.org. Amelia Pro's own source is not public, so the snippets below come from revision 3711225 of that free trunk, which the referenced files point to. In EventRepository, the plugin iterates over the tag array as $index => $value, creates a placeholder by concatenating ':tag' with $index, stores the value under that placeholder, and inserts the generated placeholder names into an et.name IN (...) condition:
$param = ':tag' . $index; $params[$param] = $value;
The value is later prepared, but $index is whatever key the client sent. If the request carries tag[<payload>]=x, the placeholder name itself becomes :tag<payload>.
Why the binder fails
The earlier Statement::execute() implementation sorts binding names by descending length, prepares each replacement value through $wpdb->prepare(), and then performs the substitution with PHP's strtr():
$query = strtr($this->statement, $replacements);
strtr() with an array performs longest-match replacement over the statement text. That is fine when the developer controls every placeholder name. When the attacker controls the names, they can choose keys that overlap, for example one name being a prefix of another. NVD states explicitly that overlapping strtr() substitution keys can defeat this binder, and newer source comments in the trunk describe longest-match behavior that could leave attacker text stranded as raw SQL. The prepared values are substituted in, but parts of the attacker-supplied names survive as executable query text.
The lesson generalizes well beyond this plugin: preparing values does not protect a query when untrusted input also determines the query's structure, including the names of the placeholders themselves.
Attack flow
Based on the advisory and the referenced source, exploitation proceeds as follows:
- The attacker sends an unauthenticated request to the events listing path handled by
GetEventsController, supplying atagarray whose keys contain SQL fragments. wp_magic_quotesescapes the array values but leaves the keys intact.- The request reaches
GetEventsCommandHandler. The handler has distinct frontend and nonfrontend branches, and authorization is invoked only inside the nonfrontend branch, which is consistent with the unauthenticated classification. This does not mean every Amelia API is public. EventRepository::getFilteredIds()builds placeholder names by concatenating':tag'with each attacker-supplied key and places them in theet.name IN (...)clause.Statement::execute()substitutes bindings withstrtr(). Crafted overlapping keys cause parts of the attacker text to remain as raw SQL, appending attacker-controlled SQL to the existing query.- Because the injection is time-based, the attacker infers data from response timing and can extract sensitive information from the database.
The advisory does not publish a timing payload, an extraction script, or a demonstrated dataset, and we have not added one. It also does not establish remote code execution, server takeover, or database destruction; the published vector scores confidentiality only.
Patch Information
Fixed version: Amelia Pro 9.9.2, released by the vendor on 4 November 2026. Wordfence lists the issue as patched, with 4.0 through 9.9.1 affected and the remediation: "Update to version 9.9.2, or a newer patched version."
What the vendor has said
The official Amelia changelog entry for 9.9.2 is short. It says the update "includes important security fixes" and that users should update right away. Its only security line reads "Resolved security vulnerabilities and implemented additional security improvements." It does not name CVE-2026-116751, the tag parameter, or the changed files. Wordfence links this changelog entry as the fix reference, and that link is what ties 9.9.2 to this CVE.
No public diff
Amelia Pro is commercial and is not published to the WordPress.org SVN repository, so no public commit, changeset, or diff for 9.9.2 was found. The Wordfence and NVD records point at these locations in the free ameliabooking trunk:
EventRepository.php#L520Statement.php#L101GetEventsCommandHandler.php#L72GetEventsController.php#L29ameliabooking.php#L1337
Treat any "patch snippet" for this CVE that circulates without a vendor source as unverified.
What a correct fix has to address
We cannot confirm exactly which changes 9.9.2 made. The following describes what a working fix needs to do based on the advisory, and can serve as a checklist if you diff 9.9.1 against 9.9.2 yourself.
- Request handling: array keys reach SQL unescaped. A proper fix ignores request-supplied keys and keeps only the values, for example by normalizing with
array_values(). It should also ensure each tag is a plain string that passes sanitizing or allowlist checks before any query is built. - Query building:
Statement::executeusesstrtr()to fill placeholders. A full fix generates placeholder names on the server, typically from a counter such as:tag0,:tag1, and so on, never from request data, or switches to$wpdb->prepare()with positional%splaceholders.
Fixing both layers is the robust approach. Fixing only the input side leaves the strtr() binder unsafe for any other caller that builds placeholder names from user data. Fixing only the binder still lets unescaped keys flow into query code.
Verifying the fixed build
In the WordPress admin dashboard, open Plugins and confirm that Booking for Appointments and Events Calendar, Amelia Pro shows version 9.9.2 or later. Anything at 9.9.1 or below, back to 4.0, remains exposed. Wordfence's advisory does not describe a CVE-specific firewall rule or temporary workaround, so updating is the documented remediation.
Affected Systems and Versions
- Product: Booking for Appointments and Events Calendar, Amelia Pro (WordPress plugin)
- Affected versions: 4.0 through 9.9.1, inclusive
- Fixed version: 9.9.2, or a newer patched version
- Configuration: no authentication or user interaction required; the vulnerable events path is reachable over the network
- Release stream caution: the reviewed WordPress.org listing for the free directory plugin shows version 2.4.14 with separate security notes. That version number is not a substitute for the Pro advisory's version guidance, so do not compare numbers across the two release streams.
Exploitation status. The reviewed sources do not establish a confirmed exploitation campaign, a named threat actor, indicators of compromise, or a published working exploit. The reviewed CISA Known Exploited Vulnerabilities catalog snapshot has no entry for this CVE, and VulDB shows KEV: no. Wordfence published its advisory on November 6, 2026 and updated it on November 7, 2026, the same day NVD published its record. A Patchstack warning that exploitation is expected concerns a different Amelia issue (CVE-2026-107616) and is not evidence of attacks against this one.
Vendor Security History
Amelia has several recent, distinct security fixes. They involve different mechanisms and access requirements, so remediation of one does not imply remediation of another.
- CVE-2026-4668: SQL injection through the
sortparameter in Amelia 2.1.2 and earlier. Exploitation requires Manager level access or higher; Wordfence describes time-based blind SQL injection capable of extracting sensitive database information and recommends 2.1.3 or a newer patched version. - CVE-2026-107616: unauthenticated missing authorization leading to arbitrary event attendee data exposure, documented by Patchstack with a fix in 9.9.2 or later. Sharing the 9.9.2 patch target with CVE-2026-116751 does not make the two issues, their exploit evidence, or any protective rules interchangeable.
- Version 9.8 (August 17, 2026): fixed an IDOR issue that could permit arbitrary user password changes, plus an SQL injection issue.
- Version 9.8.1 (August 26, 2026): included security fixes with an immediate update recommendation.
The contrast with CVE-2026-4668 is worth noting: that earlier SQL injection required an authenticated managerial role, whereas CVE-2026-116751 requires no privileges at all. The changelog shows a visible remediation history, but the reviewed material does not support conclusions about response times or an overall security ranking.
References
- NVD: CVE-2026-116751
- CVE Record: CVE-2026-116751
- Wordfence advisory: Amelia Pro 9.9.1 and earlier, Unauthenticated SQL Injection via tag Parameter Array Keys
- Amelia changelog
- Trac: ameliabooking.php line 1337
- Trac: GetEventsCommandHandler.php line 72
- Trac: GetEventsController.php line 29
- Trac: Statement.php line 101
- Trac: EventRepository.php line 520
- Trac: EventRepository.php at revision 3711225
- Trac: Statement.php at revision 3711225
- WordPress.org plugin listing: Amelia
- Amelia: About Us
- Amelia: Celebrating 8 Years of Amelia
- Wordfence: Amelia 2.1.2 and earlier, Authenticated (Manager+) SQL Injection via sort Parameter
- Patchstack: Broken Access Control in WordPress Amelia Plugin
- VulDB: CVE-2026-116751
- BugShield: CVE-2026-116751
- CISA Known Exploited Vulnerabilities Catalog
- CISA Known Exploited Vulnerabilities CSV



