| Title | mettle sendportal 3.0.1 Cross Site Scripting |
|---|
| Description | A Stored Cross-Site Scripting (XSS) vulnerability exists in mettle sendportal due to unsafe rendering of user-controlled campaign content using Laravel Blade's unescaped `{!! !!}` directive in the campaign preview and public webview functionality.
The vulnerability allows authenticated attackers to inject arbitrary JavaScript into the campaign content field through the normal application workflow. The malicious payload is stored server-side and later executed in the browser of users accessing the affected campaign preview or public `/webview/{hash}` endpoint.
The issue affects the application's trusted origin context and may lead to session hijacking, unauthorized actions, phishing attacks, and credential harvesting against users interacting with malicious campaign content.
Affected Product:
* Vendor: mettle
* Product: sendportal
* Affected Version: 3.0.1 (latest tested)
Affected Component:
* Campaign Preview
* Public Campaign Webview
Affected File:
vendor/mettle/sendportal-core/resources/views/webview/show.blade.php
Vulnerable Code:
{!! $content !!}
Technical Root Cause:
The application renders attacker-controlled campaign content using Laravel Blade's unescaped rendering directive (`{!! !!}`) instead of properly escaped rendering (`{{ }}`).
Because the campaign `content` field is user-controlled and not sanitized before storage or rendering, arbitrary HTML and JavaScript supplied by an attacker is injected directly into the DOM and executed by the victim's browser.
The issue was verified through the normal application UI and does not require database manipulation, backend access, or direct file modification.
Steps to Reproduce:
1. Install and start the application:
git clone https://github.com/mettle/sendportal.git
cd sendportal
composer install --ignore-platform-reqs
touch database/database.sqlite
cp .env.example .env
php artisan key:generate
php artisan migrate --force
php artisan serve --port=8000
2. Login as a valid workspace user.
3. Navigate to:
/campaigns/create
4. Fill the required campaign fields:
* Campaign Name
* Subject
* From Email
5. Insert the following payload into the campaign content field:
<script>alert("STORED_XSS_VERIFIED")</script>
6. Click "Save and continue".
7. Observe JavaScript execution on:
/campaigns/{id}/preview
8. Obtain the public webview URL:
/webview/{hash}
9. Open the public webview link in:
* An incognito browser session
* Another browser
* Another user session
10. Observe arbitrary JavaScript execution without authentication.
Observed Behavior:
* The payload is stored successfully.
* JavaScript executes automatically when the campaign preview page is opened.
* JavaScript also executes through the public `/webview/{hash}` endpoint.
* The issue is reproducible through normal application functionality.
Expected Behavior:
User-controlled campaign content should be sanitized or safely escaped before rendering in order to prevent arbitrary JavaScript execution.
Security Impact:
* Cross-user Stored XSS
* Remote execution of attacker-controlled JavaScript
* Execution within trusted application origin
* Potential session hijacking
* Potential CSRF token access
* Unauthorized actions via victim session
* Credential harvesting and phishing attacks
* Potential compromise of administrative users viewing malicious campaign content
Attack Requirements:
* Remote exploitation
* Low privileges required (authenticated workspace user)
* Victim interaction required (viewing malicious preview or public webview link)
CVSS 3.1 Vector:
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N
CVSS 3.1 Base Score:
8.2 (High)
CWE Classification:
CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Recommended Remediation:
1. Sanitize campaign content before storage using a trusted HTML sanitization library such as HTML Purifier.
Example:
use Mews\Purifier\Facades\Purifier;
$cleanContent = Purifier::clean($request->input('content'));
2. Avoid rendering raw user-controlled HTML using `{!! !!}` unless content is strictly sanitized beforehand.
3. Replace unsafe rendering with escaped rendering where possible:
{{ $content }}
4. Implement a strict Content Security Policy (CSP) to reduce script execution risk.
5. Consider isolating the public webview functionality on a separate origin or sandboxed environment.
Vendor Disclosure:
Vendor was contacted beforehand through public GitHub issue disclosure:
https://github.com/mettle/sendportal/issues/338
At the time of submission, no vendor response or fix was available.
Please refer the following URL for the screenshots and a detailed report:
https://drive.google.com/drive/folders/1yPH3CXOPoZVqA0c6atCDScGh_slfz6ED?usp=sharing |
|---|
| Source | ⚠️ https://github.com/mettle/sendportal/issues/338 |
|---|
| User | Superman_04 (UID 98152) |
|---|
| Submission | 05/11/2026 13:58 (3 months ago) |
|---|
| Moderation | 05/31/2026 18:31 (20 days later) |
|---|
| Status | Duplicate |
|---|
| VulDB entry | 367513 [Mettle sendportal up to 3.0.1 Campaign /webview/ content cross site scripting] |
|---|
| Points | 0 |
|---|