641 lines
23 KiB
Markdown
641 lines
23 KiB
Markdown
# SuperFunnels AI — Security Audit & Process Analysis Report
|
||
|
||
**Target:** https://app.superfunnelsai.com/app/funnel-cloner
|
||
**Date:** February 7, 2026
|
||
**Auditor:** Clawdbot Security Assessment
|
||
**Scope:** Unauthenticated + Partially Authenticated (email-unverified account)
|
||
**Note:** Full funnel-creation walkthrough was limited by lack of verified account credentials. Findings below are from the accessible attack surface.
|
||
|
||
---
|
||
|
||
## Executive Summary
|
||
|
||
**Overall Security Posture: 🔴 HIGH RISK**
|
||
|
||
SuperFunnels AI has several **critical and high-severity vulnerabilities** that need immediate attention. The most dangerous is a **wildcard CORS misconfiguration with credential reflection** across all API endpoints, which could allow any website to make authenticated requests on behalf of logged-in users — potentially stealing GHL (GoHighLevel) session tokens, API keys, and credentials.
|
||
|
||
The application is built on **Laravel + Filament 3 + Livewire 3 + React** (for the GHL login component), with **Laravel Reverb** for WebSockets and **Cloudflare** for CDN/WAF. While some security basics are in place (CSRF tokens, HttpOnly session cookies, X-Frame-Options), critical gaps exist.
|
||
|
||
### Risk Ratings Summary
|
||
|
||
| Severity | Count | Key Issues |
|
||
|----------|-------|------------|
|
||
| 🔴 Critical | 2 | CORS misconfiguration, GHL credential proxying |
|
||
| 🟠 High | 3 | Email verification bypass (API), no CSP, exposed internal infrastructure |
|
||
| 🟡 Medium | 4 | Stored XSS risk, Livewire version mismatch, Horizon exposed, debug info leaks |
|
||
| 🔵 Low | 4 | No CAPTCHA, no SRI, FirstPromoter tracking leak, cookie SameSite=Lax |
|
||
| ℹ️ Info | 4 | Tech stack fingerprinting, robots.txt, /up endpoint, WebSocket config |
|
||
|
||
---
|
||
|
||
## 1. Technology Stack Identification
|
||
|
||
| Component | Details |
|
||
|-----------|---------|
|
||
| **Framework** | Laravel (PHP) |
|
||
| **Admin Panel** | Filament v3.3.47 |
|
||
| **Frontend** | Livewire 3 + Alpine.js + React (GHL component) |
|
||
| **WebSocket** | Laravel Reverb via Pusher protocol |
|
||
| **CDN/WAF** | Cloudflare |
|
||
| **Reverse Proxy** | Nginx (behind Cloudflare) |
|
||
| **Hosting** | app.superfunnelsai.com (104.21.9.96, 172.67.189.52 — Cloudflare IPs) |
|
||
| **WebSocket Host** | ws.app.theagencytoolkit.com (178.156.167.241 — direct IP, NOT behind Cloudflare) |
|
||
| **Affiliate** | FirstPromoter (cid: `vbcs0jwr`) |
|
||
| **Monitoring** | Cloudflare Web Analytics |
|
||
| **Queue System** | Laravel Horizon (installed, 403-protected) |
|
||
| **Real-time** | Laravel Echo + Reverb |
|
||
| **GHL Integration** | Custom React component with browser extension bridge |
|
||
|
||
---
|
||
|
||
## 2. Process Walkthrough
|
||
|
||
### 2.1 Registration Flow
|
||
**URL:** `https://app.superfunnelsai.com/register`
|
||
|
||

|
||
|
||
**Fields collected:**
|
||
- Name (text, no length/format validation observed)
|
||
- Email (email type input)
|
||
- Password + Confirm Password
|
||
- Terms of Service checkbox
|
||
|
||
**Security observations:**
|
||
- ✅ CSRF `_token` hidden field present
|
||
- ✅ Email verification required after registration
|
||
- ✅ Password confirmation required
|
||
- ❌ No CAPTCHA — vulnerable to automated account creation
|
||
- ❌ No password strength requirements visible (accepted `TestPassword123!`)
|
||
- ❌ Accepts `<script>alert('XSS')</script>` as a name (stored XSS risk)
|
||
|
||
**POST to:** `https://app.superfunnelsai.com/register` (standard Laravel form submission)
|
||
|
||
### 2.2 Email Verification
|
||
**URL:** `https://app.superfunnelsai.com/app/email-verification/prompt`
|
||
|
||

|
||
|
||
- After registration, redirects to verification prompt
|
||
- "Resend it" link available
|
||
- Application routes (funnel-cloner, etc.) redirect back to verification
|
||
- **BUT:** API endpoints are accessible without email verification (see Finding #2)
|
||
|
||
### 2.3 Login Flow (Filament Auth)
|
||
**URL:** `https://app.superfunnelsai.com/app/login`
|
||
|
||

|
||
|
||
**Livewire component:** `filament.pages.auth.login`
|
||
|
||
**Data collected:**
|
||
- Email address
|
||
- Password
|
||
- Remember me checkbox
|
||
|
||
**Security observations:**
|
||
- ✅ CSRF via meta tag + Livewire's X-CSRF-TOKEN header
|
||
- ✅ Form submission via Livewire (not traditional POST)
|
||
- ✅ Password visibility toggle
|
||
- ❌ No CAPTCHA or rate limiting visible
|
||
- ❌ "Forgot password" flow untested (but endpoint exists at `/app/password-reset/request`)
|
||
|
||
### 2.4 GHL (GoHighLevel) Login Flow
|
||
**This is the core of the funnel-cloner — it requires GHL authentication.**
|
||
|
||
The flow works in two modes:
|
||
|
||
#### Mode 1: Direct Login
|
||
1. User enters GHL email + password into a React modal
|
||
2. POST to `/api/ghl-session/login` with credentials
|
||
3. If 2FA required, prompts for OTP code
|
||
4. If multiple GHL accounts, shows account selector
|
||
5. On success, stores encrypted session with "Remember" option
|
||
6. Session stored via `/api/funnel-clone/credentials`
|
||
|
||
#### Mode 2: Chrome Extension Bridge
|
||
1. User has a GHL browser extension installed
|
||
2. Extension sends message via `window.postMessage` with type `GHL_EXTENSION_READY`
|
||
3. Extension provides: `token`, `sessionToken`, `refreshedToken`, `backendAuthToken`, `lcApiAuthToken`, `apiKey`, `companyId`, `userId`, `userType`, `locationId`
|
||
4. These are POSTed to `/api/ghl-session/extension` with CSRF token
|
||
5. Session established
|
||
|
||
### 2.5 Funnel Cloner (Authenticated)
|
||
**URL:** `https://app.superfunnelsai.com/app/funnel-cloner`
|
||
*Could not fully test — requires verified email + GHL session*
|
||
|
||
Based on JS bundle analysis, the funnel cloner:
|
||
- Requires active GHL session (checks `/api/funnel-clone/credentials`)
|
||
- Uses real-time updates via Laravel Reverb WebSocket
|
||
- Has file upload capabilities (Livewire file upload component)
|
||
- Interacts with GHL API using proxied credentials
|
||
|
||
---
|
||
|
||
## 3. Security Findings
|
||
|
||
### 🔴 CRITICAL-1: Wildcard CORS with Credential Reflection
|
||
|
||
**Severity:** CRITICAL
|
||
**CVSS:** 9.1
|
||
**Affected Endpoints:** All `/api/*` routes, `/horizon/*`
|
||
|
||
The application reflects **any Origin** in the `Access-Control-Allow-Origin` header AND sets `Access-Control-Allow-Credentials: true`. This is the most dangerous CORS misconfiguration possible.
|
||
|
||
**Proof of Concept:**
|
||
```
|
||
$ curl -sI -X OPTIONS "https://app.superfunnelsai.com/api/funnel-clone/credentials" \
|
||
-H "Origin: https://evil.com" \
|
||
-H "Access-Control-Request-Method: GET"
|
||
|
||
Access-Control-Allow-Origin: https://evil.com
|
||
Access-Control-Allow-Credentials: true
|
||
Access-Control-Allow-Methods: GET
|
||
Access-Control-Allow-Headers: Content-Type, X-CSRF-TOKEN
|
||
```
|
||
|
||
**Impact:**
|
||
- Any website can make authenticated API requests as the logged-in user
|
||
- An attacker can create a malicious page that steals GHL session tokens
|
||
- GHL API keys, company IDs, user IDs, and auth tokens can be exfiltrated
|
||
- Combined with the `/api/ghl-session/extension` endpoint, an attacker could inject their own session data
|
||
|
||
**Affected endpoints confirmed:**
|
||
- `GET /api/funnel-clone/credentials` — returns GHL session data
|
||
- `POST /api/ghl-session/login` — initiates GHL login
|
||
- `POST /api/ghl-session/extension` — stores GHL session tokens
|
||
- `GET/POST /horizon/*` — queue monitoring dashboard
|
||
|
||
**Response headers also expose:**
|
||
```
|
||
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
|
||
Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin, Authorization, X-API-Key
|
||
```
|
||
|
||
### 🔴 CRITICAL-2: GHL Credential Proxying Without Adequate Protection
|
||
|
||
**Severity:** CRITICAL
|
||
**CVSS:** 8.5
|
||
|
||
The application proxies GoHighLevel credentials through its own backend. The `/api/ghl-session/extension` endpoint accepts and stores:
|
||
|
||
```json
|
||
{
|
||
"refresh_token": "...",
|
||
"token": "...",
|
||
"refreshed_token": "...",
|
||
"backend_auth_token": "...",
|
||
"lc_api_auth_token": "...",
|
||
"api_key": "...",
|
||
"company_id": "...",
|
||
"user_id": "...",
|
||
"user_type": "...",
|
||
"location_id": "...",
|
||
"remember": true
|
||
}
|
||
```
|
||
|
||
**Impact:**
|
||
- GHL API keys and auth tokens pass through the SuperFunnels server
|
||
- Combined with CORS vulnerability, these can be stolen cross-origin
|
||
- The "Remember session (encrypted)" feature stores GHL credentials server-side
|
||
- If the SuperFunnels database is compromised, all stored GHL sessions are exposed
|
||
- The direct login flow sends GHL email+password to `/api/ghl-session/login` — meaning SuperFunnels has access to plaintext GHL credentials during transit
|
||
|
||
### 🟠 HIGH-1: API Accessible Without Email Verification
|
||
|
||
**Severity:** HIGH
|
||
**CVSS:** 7.5
|
||
|
||
After registration (without email verification), API endpoints return data:
|
||
|
||
```
|
||
GET /api/funnel-clone/credentials → 200 OK
|
||
{"session":{"exists":false,"updated_at":null,"storage_state":null,"is_valid":false}}
|
||
```
|
||
|
||
**Impact:**
|
||
- Automated account creation + API abuse
|
||
- No email verification means no identity validation before API access
|
||
- Could be used to enumerate API endpoints and functionality
|
||
|
||
### 🟠 HIGH-2: No Content-Security-Policy Header
|
||
|
||
**Severity:** HIGH
|
||
**CVSS:** 7.0
|
||
|
||
The application does not set a `Content-Security-Policy` header. The meta tag check returned `none`.
|
||
|
||
**Impact:**
|
||
- XSS attacks can load external scripts, exfiltrate data, and execute arbitrary code
|
||
- No restriction on inline scripts, eval(), or external resource loading
|
||
- Combined with stored XSS vectors (see MEDIUM-1), this significantly increases attack impact
|
||
|
||
### 🟠 HIGH-3: Exposed Internal Infrastructure via WebSocket
|
||
|
||
**Severity:** HIGH
|
||
**CVSS:** 6.8
|
||
|
||
The WebSocket server at `ws.app.theagencytoolkit.com` (IP: 178.156.167.241) is **NOT behind Cloudflare**. This exposes:
|
||
|
||
1. **Direct server IP** — bypasses Cloudflare WAF/DDoS protection
|
||
2. **Reverb key:** `h7c0rpv5d85eqkixcops` (hardcoded in JS)
|
||
3. **Alternative domain:** `app.theagencytoolkit.com` redirects (308) to `app.superfunnelsai.com`
|
||
4. **WebSocket auth endpoint:** `/broadcasting/auth` (requires session cookie)
|
||
|
||
**Proof:**
|
||
```
|
||
ws.app.theagencytoolkit.com → 178.156.167.241 (direct IP, not Cloudflare)
|
||
app.superfunnelsai.com → 104.21.9.96, 172.67.189.52 (Cloudflare)
|
||
```
|
||
|
||
### 🟡 MEDIUM-1: Stored XSS Risk in Registration
|
||
|
||
**Severity:** MEDIUM
|
||
**CVSS:** 6.1
|
||
|
||
The registration form accepts `<script>alert('XSS')</script>` as a valid name. This was successfully stored (registration completed, email verification sent to `xsstest@test.com` with the XSS payload name).
|
||
|
||

|
||
|
||
**Impact:**
|
||
- If the name is rendered unsanitized anywhere (admin panel, user lists, emails), XSS will execute
|
||
- Laravel's Blade `{{ }}` escapes by default, but Livewire/Filament components or `{!! !!}` usage could bypass this
|
||
- Email templates may render the name unsanitized (HTML email XSS)
|
||
|
||
### 🟡 MEDIUM-2: Livewire Assets Version Mismatch
|
||
|
||
**Severity:** MEDIUM
|
||
**CVSS:** 5.3
|
||
|
||
A console warning is present:
|
||
```
|
||
Livewire: The published Livewire assets are out of date
|
||
```
|
||
|
||
**Impact:**
|
||
- Published assets don't match the installed Livewire version
|
||
- Could indicate missed security patches in frontend assets
|
||
- May cause functionality issues or expose known vulnerabilities
|
||
|
||
### 🟡 MEDIUM-3: Laravel Horizon Accessible (403, Not 404)
|
||
|
||
**Severity:** MEDIUM
|
||
**CVSS:** 5.0
|
||
|
||
The `/horizon` endpoint returns 403 (not 404), confirming Horizon is installed:
|
||
```
|
||
GET /horizon → 403 (with wildcard CORS headers!)
|
||
GET /horizon/api/stats → 403
|
||
GET /horizon/api/jobs/recent → 403
|
||
```
|
||
|
||
**Impact:**
|
||
- Confirms queue system usage (useful for attackers mapping the application)
|
||
- If authorization middleware is misconfigured or bypassed, exposes job queue data
|
||
- The wildcard CORS on Horizon is especially concerning
|
||
|
||
### 🟡 MEDIUM-4: Server Error on Log Viewer
|
||
|
||
**Severity:** MEDIUM
|
||
**CVSS:** 4.5
|
||
|
||
```
|
||
GET /log-viewer → 500 Internal Server Error
|
||
```
|
||
|
||
With wildcard CORS headers in the response.
|
||
|
||
**Impact:**
|
||
- Confirms log-viewer package is installed
|
||
- 500 error may indicate misconfiguration that could be exploited
|
||
- Server errors may leak stack traces in certain configurations
|
||
|
||
### 🔵 LOW-1: No CAPTCHA on Registration or Login
|
||
|
||
**Severity:** LOW
|
||
**CVSS:** 3.7
|
||
|
||
No CAPTCHA (reCAPTCHA, hCaptcha, Turnstile) on:
|
||
- Registration form
|
||
- Login form
|
||
- Password reset form
|
||
|
||
**Impact:**
|
||
- Automated account creation (spam/abuse)
|
||
- Credential stuffing attacks
|
||
- Brute force on login (though CSRF adds friction)
|
||
|
||
### 🔵 LOW-2: No Subresource Integrity (SRI) on External Scripts
|
||
|
||
**Severity:** LOW
|
||
**CVSS:** 3.5
|
||
|
||
External scripts loaded without SRI hashes:
|
||
```html
|
||
<script src="https://cdn.firstpromoter.com/fpr.js" async></script>
|
||
<script src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015"></script>
|
||
```
|
||
|
||
**Impact:**
|
||
- If CDN is compromised, malicious code could be injected
|
||
- Especially concerning with no CSP to limit script sources
|
||
|
||
### 🔵 LOW-3: FirstPromoter Customer ID Exposed
|
||
|
||
**Severity:** LOW
|
||
**CVSS:** 2.0
|
||
|
||
```javascript
|
||
fpr("init", {cid:"vbcs0jwr"});
|
||
```
|
||
|
||
**Impact:**
|
||
- Reveals affiliate tracking program details
|
||
- Could be used for competitive intelligence
|
||
|
||
### 🔵 LOW-4: Cookie SameSite=Lax (Not Strict)
|
||
|
||
**Severity:** LOW
|
||
**CVSS:** 2.5
|
||
|
||
```
|
||
Set-Cookie: XSRF-TOKEN=...; secure; samesite=lax
|
||
Set-Cookie: superfunnels_ai_session=...; secure; httponly; samesite=lax
|
||
```
|
||
|
||
While `Lax` is generally acceptable, `Strict` would provide better CSRF protection. However, the session cookie properly has `HttpOnly` and `Secure` flags.
|
||
|
||
### ℹ️ INFO-1: Technology Stack Easily Fingerprinted
|
||
|
||
- Filament admin panel identified via Livewire component names (`filament.pages.auth.login`)
|
||
- Laravel identified via cookie naming (`XSRF-TOKEN`, `superfunnels_ai_session`)
|
||
- Livewire version detectable via published assets warning
|
||
- Pusher/Reverb configuration visible in client-side JavaScript
|
||
- Alpine.js usage confirmed via event dispatching patterns
|
||
|
||
### ℹ️ INFO-2: Health Check Endpoint Exposed
|
||
|
||
```
|
||
GET /up → 200 OK
|
||
"Application up - HTTP request received. Response rendered in 89ms."
|
||
```
|
||
|
||
Reveals server response time and application status.
|
||
|
||
### ℹ️ INFO-3: Debug Logging in Client-Side Code
|
||
|
||
The notification listener script includes extensive `console.log` and `console.warn` debug output:
|
||
```javascript
|
||
console.log("🔍 User ID detection debug:", {...})
|
||
console.warn("🔇 No user ID found, cannot listen for notifications")
|
||
console.warn("🔍 Debug - All available data:", {filamentData, Laravel, metaTagsCount, allMetaTags})
|
||
```
|
||
|
||
This exposes internal data structures to anyone with browser DevTools open.
|
||
|
||
### ℹ️ INFO-4: URL Parameter Modal Injection
|
||
|
||
The `openModal` URL parameter accepts arbitrary modal IDs and dispatches Alpine.js events:
|
||
```javascript
|
||
window.dispatchEvent(new CustomEvent('open-modal', {
|
||
detail: { id: modalId }
|
||
}));
|
||
```
|
||
|
||
While not directly exploitable for XSS (the value goes into querySelector and CustomEvent detail), it could potentially trigger unintended UI actions.
|
||
|
||
---
|
||
|
||
## 4. Network Analysis
|
||
|
||
### API Endpoints Discovered
|
||
|
||
| Endpoint | Method | Auth Required | Purpose |
|
||
|----------|--------|---------------|---------|
|
||
| `/api/funnel-clone/credentials` | GET | Yes (unverified OK) | Get GHL session status |
|
||
| `/api/funnel-clone/credentials` | DELETE | Yes | Forget stored GHL session |
|
||
| `/api/ghl-session/login` | POST | Yes + CSRF | Initiate GHL login |
|
||
| `/api/ghl-session/extension` | POST | Yes + CSRF | Store GHL session from extension |
|
||
| `/api/first-login-video/ack` | POST | Yes + CSRF | Acknowledge first-login video shown |
|
||
| `/livewire/update` | POST | CSRF | Livewire component updates |
|
||
| `/broadcasting/auth` | POST | Session | WebSocket channel authorization |
|
||
| `/broadcasting/user-auth` | POST | Session | WebSocket user authentication |
|
||
|
||
### External Services Called
|
||
|
||
| Service | Domain | Purpose |
|
||
|---------|--------|---------|
|
||
| Cloudflare | `static.cloudflareinsights.com` | Web analytics |
|
||
| FirstPromoter | `cdn.firstpromoter.com` | Affiliate tracking |
|
||
| Bunny Fonts | `fonts.bunny.net` | Web fonts |
|
||
| Google Cloud Storage | `storage.googleapis.com/msgsndr/...` | Media/videos |
|
||
| Laravel Reverb | `ws.app.theagencytoolkit.com` | Real-time WebSocket |
|
||
|
||
### Response Header Analysis
|
||
|
||
| Header | Value | Assessment |
|
||
|--------|-------|------------|
|
||
| `X-Frame-Options` | `SAMEORIGIN` | ✅ Good |
|
||
| `X-XSS-Protection` | `1; mode=block` | ⚠️ Deprecated (CSP preferred) |
|
||
| `X-Content-Type-Options` | `nosniff` | ✅ Good |
|
||
| `Content-Security-Policy` | **MISSING** | ❌ Critical gap |
|
||
| `Strict-Transport-Security` | **MISSING** | ⚠️ Should be set |
|
||
| `Referrer-Policy` | **MISSING** | ⚠️ Should be set |
|
||
| `Permissions-Policy` | **MISSING** | ⚠️ Should be set |
|
||
| `Cache-Control` | `no-cache, no-store, private` | ✅ Good for auth pages |
|
||
| `Server` | `cloudflare` / `nginx` | ℹ️ Mixed (Cloudflare + origin leak) |
|
||
|
||
---
|
||
|
||
## 5. Client-Side Analysis
|
||
|
||
### JavaScript Bundles
|
||
|
||
| File | Size | Contents |
|
||
|------|------|----------|
|
||
| `app-CQli-r76.js` | 222 KB | Axios, Pusher, Echo, GHL login React app |
|
||
| `useGhlHttpLogin-B2Y3P8yM.js` | 158 KB | React, GHL login form components |
|
||
| `livewire.min.js` | Large | Livewire core (outdated published version) |
|
||
| `filament-monaco-editor-scripts.js` | — | Monaco editor (code editing capability) |
|
||
| `filament-code-field.js` | — | Code field component |
|
||
| `filament-code-editor.js` | — | Code editor component |
|
||
|
||
### Hardcoded Values Found
|
||
|
||
| Item | Value | Risk |
|
||
|------|-------|------|
|
||
| Reverb/Pusher Key | `h7c0rpv5d85eqkixcops` | Medium (public key, but reveals infra) |
|
||
| WebSocket Host | `ws.app.theagencytoolkit.com` | High (direct IP exposed) |
|
||
| FirstPromoter CID | `vbcs0jwr` | Low |
|
||
| Auth endpoint | `/broadcasting/auth` | Info |
|
||
| GCP Storage Bucket | `storage.googleapis.com/msgsndr/Sr99nTAsuyCabfQCL1JQ` | Info |
|
||
|
||
### localStorage Data
|
||
|
||
```json
|
||
{
|
||
"theme": "light",
|
||
"pusherTransportTLS": {"timestamp":1770427824413,"transport":"xhr_streaming","latency":3007},
|
||
"isOpen": "true",
|
||
"collapsedGroups": "null"
|
||
}
|
||
```
|
||
No sensitive data in localStorage. ✅
|
||
|
||
### sessionStorage Data
|
||
|
||
```json
|
||
{}
|
||
```
|
||
Clean (GHL login return URL stored temporarily during login flow).
|
||
|
||
### Cookie Security
|
||
|
||
| Cookie | Secure | HttpOnly | SameSite | Assessment |
|
||
|--------|--------|----------|----------|------------|
|
||
| `XSRF-TOKEN` | ✅ | ❌ | Lax | Expected (JS needs access) |
|
||
| `superfunnels_ai_session` | ✅ | ✅ | Lax | ✅ Good |
|
||
|
||
---
|
||
|
||
## 6. Input Validation Results
|
||
|
||
### Registration Form
|
||
|
||
| Payload | Field | Result |
|
||
|---------|-------|--------|
|
||
| `<script>alert('XSS')</script>` | Name | ⚠️ **Accepted** — stored in DB |
|
||
| `xsstest@test.com` | Email | Accepted (valid format) |
|
||
| `TestPassword123!` | Password | Accepted |
|
||
|
||
**Note:** Full XSS execution testing could not be completed as the name value needs to be rendered in authenticated views (admin dashboard, user lists, etc.) to confirm if it executes. However, the storage of unvalidated HTML in the name field is a vulnerability regardless.
|
||
|
||
### CSRF Protection
|
||
|
||
| Endpoint | CSRF Protected | Method |
|
||
|----------|---------------|--------|
|
||
| Registration | ✅ `_token` hidden field | HTML form |
|
||
| Login | ✅ via Livewire meta tag | AJAX |
|
||
| API routes | ✅ CSRF required | Returns 419 on mismatch |
|
||
| GHL session endpoints | ✅ X-CSRF-TOKEN header | AJAX |
|
||
|
||
### Authentication Bypass
|
||
|
||
| Attempt | Result |
|
||
|---------|--------|
|
||
| Access `/app/funnel-cloner` without email verify | Redirected to verify page ✅ |
|
||
| Access `/api/funnel-clone/credentials` without email verify | **200 OK — data returned** ❌ |
|
||
| Access API without any auth | 401 Unauthenticated ✅ |
|
||
|
||
---
|
||
|
||
## 7. Recommendations
|
||
|
||
### 🔴 IMMEDIATE (Critical — Fix Now)
|
||
|
||
1. **Fix CORS Configuration**
|
||
- Remove wildcard origin reflection
|
||
- Whitelist specific allowed origins: `['https://app.superfunnelsai.com']`
|
||
- **Never** combine `Access-Control-Allow-Origin: *` with `Access-Control-Allow-Credentials: true`
|
||
- In Laravel, update `config/cors.php`:
|
||
```php
|
||
'allowed_origins' => ['https://app.superfunnelsai.com'],
|
||
'supports_credentials' => true,
|
||
```
|
||
|
||
2. **Audit GHL Credential Flow**
|
||
- Consider using OAuth 2.0 with GHL instead of proxying raw credentials
|
||
- If credential proxying is required, ensure encryption at rest with per-user keys
|
||
- Implement token rotation for stored sessions
|
||
- Add warning/consent for users about credential handling
|
||
|
||
### 🟠 HIGH PRIORITY (Fix This Week)
|
||
|
||
3. **Enforce Email Verification on API Routes**
|
||
- Add `verified` middleware to all API routes:
|
||
```php
|
||
Route::middleware(['auth', 'verified'])->group(function () {
|
||
Route::get('/api/funnel-clone/credentials', ...);
|
||
});
|
||
```
|
||
|
||
4. **Implement Content-Security-Policy**
|
||
```
|
||
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.firstpromoter.com https://static.cloudflareinsights.com 'nonce-{random}'; style-src 'self' https://fonts.bunny.net 'unsafe-inline'; font-src 'self' https://fonts.bunny.net; img-src 'self' data: https:; connect-src 'self' wss://ws.app.theagencytoolkit.com; frame-src 'self'
|
||
```
|
||
|
||
5. **Move WebSocket Behind Cloudflare**
|
||
- `ws.app.theagencytoolkit.com` should use Cloudflare proxy
|
||
- This exposes the origin server IP, bypassing all Cloudflare protections
|
||
|
||
### 🟡 MEDIUM PRIORITY (Fix This Sprint)
|
||
|
||
6. **Add Input Validation on Name Field**
|
||
- Strip HTML tags from name input
|
||
- Add maximum length validation
|
||
- Consider alphanumeric + common characters only regex
|
||
|
||
7. **Update Livewire Published Assets**
|
||
```bash
|
||
php artisan livewire:publish --assets
|
||
```
|
||
|
||
8. **Remove or Properly Secure Horizon & Log Viewer**
|
||
- Ensure these return 404 (not 403/500) for unauthenticated users
|
||
- Or properly gate behind admin authentication
|
||
|
||
9. **Remove Debug Logging from Production**
|
||
- Remove all `console.log`/`console.warn` debug statements from production JavaScript
|
||
- Especially the user ID detection debug output
|
||
|
||
### 🔵 LOW PRIORITY (Backlog)
|
||
|
||
10. **Add CAPTCHA** — Cloudflare Turnstile recommended (already on Cloudflare)
|
||
11. **Add SRI hashes** to external script tags
|
||
12. **Add missing security headers:**
|
||
- `Strict-Transport-Security: max-age=31536000; includeSubDomains`
|
||
- `Referrer-Policy: strict-origin-when-cross-origin`
|
||
- `Permissions-Policy: camera=(), microphone=(), geolocation=()`
|
||
13. **Consider SameSite=Strict** for session cookie
|
||
14. **Remove `/up` endpoint** from public access or add authentication
|
||
|
||
---
|
||
|
||
## 8. Limitations
|
||
|
||
This audit was conducted with the following limitations:
|
||
|
||
1. **No verified account access** — Could not test the full funnel-cloner workflow
|
||
2. **No GHL account integration** — Could not test the GHL login and credential storage flow end-to-end
|
||
3. **No admin panel access** — Could not verify stored XSS execution in admin views
|
||
4. **Black-box testing only** — No source code access
|
||
5. **No load/stress testing** — Rate limiting not fully verified
|
||
6. **No mobile testing** — Desktop browser only
|
||
7. **Single session** — No multi-user interaction testing
|
||
|
||
### Recommended Next Steps
|
||
|
||
1. **Provide authenticated access** (verified account + GHL integration) for deep testing of:
|
||
- Funnel creation workflow
|
||
- GHL session management
|
||
- File upload functionality
|
||
- Template testing
|
||
- IDOR testing between user accounts
|
||
|
||
2. **Source code review** (if available) for:
|
||
- Server-side credential encryption implementation
|
||
- Database schema for GHL token storage
|
||
- Middleware chain verification
|
||
- Rate limiting implementation
|
||
|
||
3. **Penetration testing** with:
|
||
- WebSocket protocol testing
|
||
- Livewire component fuzzing
|
||
- API endpoint enumeration behind auth
|
||
|
||
---
|
||
|
||
*Report generated by Clawdbot Security Assessment*
|
||
*All findings should be verified and triaged by the development team before implementing fixes.*
|