Brief Summary: Amelia WordPress Plugin CVE-2026-5465 IDOR Privilege Escalation via externalId Parameter

A short review of CVE-2026-5465, an Insecure Direct Object Reference in the Amelia WordPress booking plugin that allows Employee-level users to take over any account, including Administrator. Includes patch analysis and affected version details.

CVE Analysis

8 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-04-06

Brief Summary: Amelia WordPress Plugin CVE-2026-5465 IDOR Privilege Escalation via externalId Parameter
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A missing authorization check in a single field of the Amelia WordPress booking plugin gives any Employee level user a direct path to full Administrator account takeover. With over 90,000 active installations and a trivial exploitation path requiring no special tooling, CVE-2026-5465 is a vulnerability that WordPress administrators running multi provider booking setups should address without delay.

The Booking for Appointments and Events Calendar, known as Amelia, is a popular WordPress plugin that provides appointment scheduling, event booking, and calendar management for service based businesses. With over 90,000 active installations, it serves a broad range of industries from salons and clinics to consulting firms. Its role based access model includes Provider (Employee) accounts, which are often assigned to staff or contractors who manage their own schedules through the WordPress backend.

Technical Information

Root Cause: Authorization Bypass via User Controlled Key (CWE-639)

The vulnerability resides in the UpdateProviderCommandHandler class, specifically in how it processes profile update requests from Provider (Employee) users. The core issue is that the handler merges all user submitted fields into the updated user object using array_merge($oldUser->toArray(), $providerData) without restricting which fields a non-admin user is permitted to modify.

Among the merged fields is externalId, which directly maps to a WordPress user ID. This field is not merely a display value; it is subsequently consumed by two critical WordPress core functions:

  1. wp_set_password() at line 219, which sets the password for the WordPress user identified by externalId.
  2. wp_update_user() at line 239, which updates the profile details (email, name, etc.) of the WordPress user identified by externalId.

Because no server side check exists to prevent a non-admin user from changing their externalId to any arbitrary value, the entire chain from field submission to privileged WordPress function execution is unguarded.

Attack Flow

The exploitation path is straightforward:

  1. The attacker authenticates to WordPress with a Provider (Employee) account. This is the minimum privilege level required.
  2. The attacker initiates a profile update request through the Amelia plugin interface. This request hits the UpdateProviderController at line 30, which delegates to the UpdateProviderCommandHandler.
  3. The attacker intercepts the outgoing HTTP request (using a proxy or browser developer tools) and modifies the externalId parameter in the request body to the WordPress user ID of the target account. For example, user ID 1 is typically the site's original Administrator.
  4. The attacker also includes their desired new password in the request payload.
  5. The UpdateProviderCommandHandler merges the submitted data with the existing provider record via array_merge(), accepting the attacker supplied externalId without question.
  6. The handler calls wp_set_password() with the attacker's chosen password and the injected externalId (the Administrator's WordPress user ID), effectively resetting the Administrator's password.
  7. The handler calls wp_update_user() with the injected externalId, potentially overwriting the Administrator's email and other profile fields.
  8. The attacker logs in as the Administrator using the newly set password.

CVSS 3.1 Breakdown

MetricValueImplication
Attack VectorNetworkExploitable remotely over the internet
Attack ComplexityLowNo advanced techniques or race conditions required
Privileges RequiredLowRequires only basic Employee or Provider access
User InteractionNoneNo victim action needed
Confidentiality ImpactHighFull access to all site data
Integrity ImpactHighComplete control over site content and configuration
Availability ImpactHighAttacker can lock out legitimate administrators

The overall score of 8.8 (High) accurately reflects the combination of low barrier to entry and total site compromise on success.

Patch Information

The vendor addressed CVE-2026-5465 in version 2.2 of the Amelia plugin. The fix is tracked in the WordPress plugin repository under changeset 3499608.

The patch introduces a targeted authorization guard immediately after the new user entity is constructed from the merged data. The following block was added right after the UserFactory::create($newUserData) call:

$oldExternalId = $oldUser->getExternalId() ? $oldUser->getExternalId()->getValue() : null; $newExternalId = $newUser->getExternalId() ? $newUser->getExternalId()->getValue() : null; if ($oldExternalId !== $newExternalId && (!$currentUser || $currentUser->getType() !== AbstractUser::USER_ROLE_ADMIN)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update user.'); return $result; }

This code compares the externalId already stored on the existing provider record ($oldExternalId) against the externalId value present in the incoming update request ($newExternalId). If the two values differ, meaning someone attempted to switch which WordPress user this provider is linked to, and the currently logged in user is not an Administrator, the handler immediately returns an error and halts execution. This prevents the tampered externalId from ever reaching the downstream wp_set_password() or wp_update_user() calls.

The placement of this fix is notable: it acts as a final gatekeeper after all field merging has already occurred but before any privileged WordPress operations execute. Only Administrators are permitted to reassign the externalId mapping, which is the correct authorization model. Employees should never be able to re-link their Amelia provider profile to a different WordPress account.

To apply the fix, update to Amelia version 2.2 or later via the standard WordPress plugin update mechanism. After updating, verify that the active version reflects 2.2 in the WordPress plugin dashboard. The patched source can be reviewed directly in the version 2.2 tag.

Affected Systems and Versions

All versions of the Booking for Appointments and Events Calendar, Amelia plugin for WordPress from the initial release through version 2.1.3 (inclusive) are vulnerable. The fix was introduced in version 2.2.

Organizations should prioritize patching systems where third party users, contractors, or lower privileged staff hold Provider or Employee roles within the Amelia system, as these accounts possess the exact prerequisites needed to exploit the vulnerability.

References

Detect & fix
what others miss

Security magnifying glass visualization