2026-02-06 23:01:30 -05:00

23 KiB
Raw Permalink Blame History

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

Registration Page

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

Email Verification

  • 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

Login Page

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:

{
  "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).

XSS Test Result

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:

<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

fpr("init", {cid:"vbcs0jwr"});

Impact:

  • Reveals affiliate tracking program details
  • Could be used for competitive intelligence

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:

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:

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

{
  "theme": "light",
  "pusherTransportTLS": {"timestamp":1770427824413,"transport":"xhr_streaming","latency":3007},
  "isOpen": "true",
  "collapsedGroups": "null"
}

No sensitive data in localStorage.

sessionStorage Data

{}

Clean (GHL login return URL stored temporarily during login flow).

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:
      '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)

  1. Enforce Email Verification on API Routes

    • Add verified middleware to all API routes:
      Route::middleware(['auth', 'verified'])->group(function () {
          Route::get('/api/funnel-clone/credentials', ...);
      });
      
  2. 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'
    
  3. 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)

  1. Add Input Validation on Name Field

    • Strip HTML tags from name input
    • Add maximum length validation
    • Consider alphanumeric + common characters only regex
  2. Update Livewire Published Assets

    php artisan livewire:publish --assets
    
  3. Remove or Properly Secure Horizon & Log Viewer

    • Ensure these return 404 (not 403/500) for unauthenticated users
    • Or properly gate behind admin authentication
  4. 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)

  1. Add CAPTCHA — Cloudflare Turnstile recommended (already on Cloudflare)
  2. Add SRI hashes to external script tags
  3. Add missing security headers:
    • Strict-Transport-Security: max-age=31536000; includeSubDomains
    • Referrer-Policy: strict-origin-when-cross-origin
    • Permissions-Policy: camera=(), microphone=(), geolocation=()
  4. Consider SameSite=Strict for session cookie
  5. 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
  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.