| Название | Mettle SendPortal Latest Authorization Bypass |
|---|
| Описание | Full technical report, proof-of-concept requests, screenshots, database evidence, execution traces, and reproduction artifacts are available at:
https://drive.google.com/drive/folders/1QpJxsfmivyzsszX5slQkXIVv-LPzBy8X?usp=sharing
Title: Cross-Tenant Authorization Bypass Allows Campaigns to Reference Another Workspace's Email Service
Vendor: Mettle
Product: SendPortal
Affected Version: Latest
Class: Authorization Bypass / Cross-Tenant Access Control Failure
CWE: CWE-639 – Authorization Bypass Through User-Controlled Key
Summary
A cross-tenant authorization bypass exists in SendPortal's campaign creation functionality. The application validates only that a supplied email_service_id exists in the database and does not verify that the referenced EmailService belongs to the authenticated user's workspace.
As a result, a user from Workspace B can create a campaign referencing an EmailService owned by Workspace A. During campaign dispatch, the application resolves and operates on the foreign EmailService object without performing any workspace ownership validation.
Technical Details
The campaign creation validation performs a global existence check:
exists:sendportal_email_services,id
The validation does not scope the lookup to the current workspace.
A campaign can therefore be created with:
* campaign.workspace_id = 2
* email_service_id = 1
where email_service_id = 1 belongs to workspace_id = 1.
During dispatch, ResolveEmailService loads the EmailService associated with the campaign through the stored foreign key. No ownership verification is performed before returning the EmailService object.
Observed execution trace:
campaign.id = 2
campaign.workspace_id = 2
campaign.email_service_id = 1
email_service.id = 1
email_service.workspace_id = 1
Result:
A campaign belonging to workspace 2 resolves an EmailService belonging to workspace 1.
Expected Behavior
Campaigns should only be allowed to reference EmailService records owned by the same workspace.
The application should reject attempts to associate resources belonging to other tenants.
Actual Behavior
The application accepts cross-workspace email_service_id values and later resolves the foreign EmailService during campaign processing without validating ownership.
Impact
* Cross-tenant resource access
* Broken workspace isolation
* Authorization bypass through user-controlled identifier
* Campaigns can be configured to operate on resources belonging to another tenant
* Core multi-tenant security boundary violation
Steps to Reproduce
1. Create two independent workspaces.
2. Create an EmailService in Workspace A.
3. Ensure Workspace B has no EmailServices.
4. Authenticate as a Workspace B user.
5. Create a campaign using email_service_id belonging to Workspace A.
6. Observe successful campaign creation.
7. Verify the campaign record stores:
* workspace_id = Workspace B
* email_service_id = Workspace A service
8. Trigger campaign processing.
9. Observe that ResolveEmailService resolves and returns the EmailService belonging to Workspace A.
Evidence
The full report includes:
* Source code references
* Validation logic analysis
* Database state before and after exploitation
* Campaign creation requests and responses
* Dispatch pipeline execution traces
* Cross-tenant resolution evidence
* Recommended remediation
All supporting material is available in the linked report.
|
|---|
| Источник | ⚠️ https://github.com/mettle/sendportal/issues/339 |
|---|
| Пользователь | Superman_04 (UID 98152) |
|---|
| Представление | 08.06.2026 16:38 (1 месяц назад) |
|---|
| Модерация | 09.07.2026 07:33 (1 month later) |
|---|
| Статус | принято |
|---|
| Запись VulDB | 377117 [mettle sendportal до 3.0.1 Campaign Creation Endpoint CampaignStoreRequest.php эскалация привилегий] |
|---|
| Баллы | 20 |
|---|