Immich Security Testing: Default Credentials, API Key Exposure, Face Recognition Data, and Shared Albums

Immich is the most widely deployed self-hosted photo and video management platform, used as a privacy-respecting Google Photos alternative with AI-powered search, face recognition, and automatic organization. Its security profile has significant privacy implications: Immich's default admin account (admin@immich.app / password) documented in the official getting started guide is frequently unchanged in home lab and small team deployments — admin access yields all photos and videos across every user account on the instance; per-user API keys generated in account settings give programmatic access to all photos, albums, faces, and metadata without requiring a session cookie — API keys stored in automation scripts risk long-lived credential exposure; Immich's machine learning service performs facial recognition on all uploaded photos and stores biometric face embeddings in the PostgreSQL database associated with identified persons — a database dump or unauthorized API access to /api/faces constitutes biometric data exposure with significant GDPR and privacy implications; shared album links create publicly accessible share tokens at /share/{token} that deliver all album photos without authentication; and EXIF metadata in uploaded photos may contain GPS coordinates, device identifiers, and timestamps — verify that Immich's metadata stripping settings are configured appropriately for the deployment's privacy requirements before sharing assets. This guide covers systematic Immich security assessment.

Table of Contents

  1. Default Credential Testing
  2. API Key Scope and Extraction
  3. Face Recognition Data Access
  4. Shared Album Link Exposure
  5. Immich Security Hardening

Default Credential Testing

# Immich default admin credentials: admin@immich.app / password
# Documented in official quick start — commonly unchanged in home lab deployments

IMMICH_URL="https://photos.example.com"

# Authenticate with default credentials
RESPONSE=$(curl -s -X POST "${IMMICH_URL}/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@immich.app","password":"password"}' 2>/dev/null)

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

if [ -n "$TOKEN" ]; then
  echo "DEFAULT CREDENTIALS WORK — admin access obtained"
  # List all users on the instance
  curl -s "${IMMICH_URL}/api/users" \
    -H "Authorization: Bearer ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
if isinstance(d,list):
    print(f'Users: {len(d)}')
    for u in d[:5]:
        print(f\"  {u.get('email','?')} admin={u.get('isAdmin','?')} photos={u.get('assetCount','?')}\")
" 2>/dev/null
fi

API Key Scope and Extraction

# Immich API keys are per-user and give full access to that user's photos
# Keys are created in Account Settings → API Keys and stored as plaintext in scripts

API_KEY="your-immich-api-key"
IMMICH_URL="https://photos.example.com"

# List all assets (photos/videos) accessible with this API key
curl -s -X POST "${IMMICH_URL}/api/assets/search" \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"size":10,"page":1}' 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
assets = d.get('assets',{}).get('items',[])
total = d.get('assets',{}).get('total',0)
print(f'Photos accessible: {total} total')
for a in assets[:5]:
    print(f\"  {a.get('originalFileName','?')} type={a.get('type','?')} date={a.get('fileCreatedAt','?')[:10]}\")
    # Check for GPS data in EXIF
    exif = a.get('exifInfo',{})
    if exif.get('latitude'):
        print(f\"    GPS: {exif['latitude']},{exif['longitude']}\")
" 2>/dev/null

# Get statistics for this account
curl -s "${IMMICH_URL}/api/server/statistics" \
  -H "x-api-key: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Photos: {d.get(\"photos\",\"?\")} Videos: {d.get(\"videos\",\"?\")} Storage: {d.get(\"usage\",\"?\")}\')
" 2>/dev/null

Immich Security Hardening

Immich Security Hardening Checklist:
Security TestMethodRisk
Default admin@immich.app/password credentialsPOST /api/auth/login with defaults — admin token grants access to all users' photos across entire instanceCritical
API key with full photo accessx-api-key header on /api/assets/search — returns all photos including EXIF GPS coordinates and personal identifiersHigh
Face recognition biometric data accessible via APIGET /api/faces or /api/people — returns face bounding boxes, biometric embeddings, and person associationsHigh
Shared album links accessible without authenticationGET /share/{token} — all photos in shared album viewable without any login by anyone with the tokenMedium
GPS EXIF data in shared photosPhoto EXIF metadata in shared album responses may contain GPS coordinates revealing locations visitedMedium
Admin API listing all users and photo countsGET /api/users with admin token — lists all accounts, email addresses, photo counts, and storage usageHigh

Automate Immich Security Testing

Ironimo tests Immich deployments for default admin@immich.app/password credentials providing access to all users' photos, API key extraction from automation scripts giving full photo and metadata access, face recognition biometric data exposure via the faces and people API endpoints, shared album tokens accessible without authentication exposing all album contents, GPS EXIF metadata in photos shared via public album links revealing location history, and admin API user enumeration listing all accounts and their photo libraries.

Start free scan