CVE-2026-46708 Overview
EspoCRM is an open source customer relationship management (CRM) application. CVE-2026-46708 is a broken access control vulnerability [CWE-639] in the OptOutService component. A low-privileged authenticated user who can access a shared TargetList can invoke opt-out or cancel-opt-out actions against protected Contact or Lead records that the user cannot read or edit. The service validates access to the target list but retrieves the target record without record-level authorization checks. This allows unauthorized modification of the opted_out relationship state on records otherwise restricted from the user. The issue is fixed in EspoCRM version 9.3.7.
Critical Impact
Low-privileged users can tamper with opt-out status on protected Contacts and Leads, corrupting marketing consent data and bypassing record-level access controls.
Affected Products
- EspoCRM versions prior to 9.3.7
- EspoCRM open source CRM deployments exposing shared TargetList entities
- Any EspoCRM instance using the Crm module OptOutService
Discovery Timeline
- 2026-10-15 - CVE-2026-46708 published to NVD
- 2026-10-15 - Last updated in NVD database
Technical Details for CVE-2026-46708
Vulnerability Analysis
The vulnerability resides in the optOut method of application/Espo/Modules/Crm/Tools/TargetList/OptOutService.php. The method validates that the caller has edit access to the parent TargetList through getTargetListForEdit($id). It then retrieves the target entity (a Contact or Lead) using entityManager->getEntityById(), which performs no record-level authorization. As a result, the service mutates the opted_out relationship state on records the acting user has no permission to read or edit. This breaks the EspoCRM authorization model, which expects every write path to enforce per-record ACLs.
Root Cause
The root cause is a missing authorization check on the target record, classified as Authorization Bypass Through User-Controlled Key [CWE-639]. The attacker supplies a targetId of their choosing, and the service trusts that TargetList membership alone implies permission to modify the referenced entity. Record-level ACLs on Contact and Lead are never evaluated inside the opt-out flow.
Attack Vector
Exploitation requires an authenticated low-privileged account with access to a shared TargetList. The attacker calls the opt-out or cancel-opt-out endpoint with a valid targetType and an arbitrary targetId. No user interaction is required. The attack is network-reachable over the standard EspoCRM HTTP API.
public function optOut(string $id, string $targetType, string $targetId): void
{
$targetList = $this->getTargetListForEdit($id);
-
- $target = $this->entityManager->getEntityById($targetType, $targetId);
-
- if (!$target) {
- throw new NotFound();
- }
+ $target = $this->entityProvider->get($targetType, $targetId);
$map = $this->metadataProvider->getEntityTypeLinkMap();
Source: GitHub Commit 5be5919. The patch replaces the raw entityManager->getEntityById() call with entityProvider->get(), which enforces the required record authorization before returning the entity.
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-46708
Indicators of Compromise
- Unexpected changes to the opted_out field on Contact or Lead records lacking a corresponding audit trail from an authorized user.
- HTTP requests to EspoCRM opt-out endpoints referencing targetId values the acting user has no read access to.
- Spikes in opt-out or cancel-opt-out API calls originating from low-privileged accounts.
Detection Strategies
- Review EspoCRM application logs for calls to OptOutService::optOut and cancelOptOut correlated with user roles that lack ACL rights on the affected records.
- Compare pre- and post-change snapshots of Contact and Lead opt-out states against expected marketing workflow activity.
- Alert on repeated 2xx responses to opt-out endpoints from the same low-privileged session across many distinct targetId values.
Monitoring Recommendations
- Enable verbose audit logging on TargetList, Contact, and Lead entities to capture relationship state changes.
- Forward EspoCRM web server and application logs to a centralized SIEM for correlation with user role context.
- Monitor outbound email suppression lists for unexplained additions or removals that correlate with EspoCRM opt-out changes.
How to Mitigate CVE-2026-46708
Immediate Actions Required
- Upgrade all EspoCRM instances to version 9.3.7 or later.
- Audit TargetList sharing to limit which users can access shared lists containing sensitive Contacts or Leads.
- Review recent opted_out state changes on Contact and Lead records and reconcile with legitimate marketing activity.
Patch Information
The fix is included in EspoCRM Release 9.3.7. Details are documented in GitHub Security Advisory GHSA-mqp6-23xq-7q3r. The code change is in commit 5be5919, which routes target record retrieval through the authorization-aware entityProvider.
Workarounds
- Restrict access to shared TargetList entities so only trusted roles can view or edit them until the patch is applied.
- Temporarily disable mass opt-out workflows that rely on shared TargetLists for low-privileged roles.
- Enforce stricter role definitions that remove TargetList edit permissions from accounts without legitimate marketing responsibilities.
# Upgrade EspoCRM to the patched version
cd /path/to/espocrm
php command.php upgrade --version=9.3.7
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

