Seven security issues from an audit, plus album pages and the map coming
up empty against Immich 3.x. Verified against a real Immich 3.0.3
instance in a production build.
Security:
- Admin session forgery via a hardcoded 'dev-fallback-secret' signing key
that bypassed the production AUTH_SECRET guard
- /api/map ignored album passwords and returned working asset tokens;
rewriting ?size=thumbnail to ?size=original downloaded full-resolution
originals from protected albums
- Admin login had no rate limit, and the client IP came from a spoofable
header, so rotating it bypassed every limit in the app
- Raw Immich asset UUIDs were serialized into the RSC payload
- Album tokens never expired server-side; a captured token replayed forever
- Path traversal into the Immich API via an unvalidated album id
- /admin ran with no enforced CSP (only Report-Only reached it)
TRUSTED_PROXIES is replaced by TRUSTED_PROXY_HOPS. The old variable
matched proxy IPs against the socket peer address, which self-hosted
Next.js never exposes, so the check could never pass: unset, the limiter
read a spoofable header; set, every request shared one bucket and a single
client could rate-limit the whole site. Migrates automatically.
Immich 3.x: GET /albums/:id no longer embeds assets. Assets now come from
POST /search/metadata with withExif: true — without that flag EXIF is
omitted and grid aspect ratios, the lightbox panel and map markers stay
empty. Drops support for Immich below 3.0, which now logs a warning.
Upgrade: requires Immich 3.0+; set TRUSTED_PROXY_HOPS (nginx = 1);
visitors of protected areas and admin sessions must log in once more.
91 unit tests (25 new); the new admin-auth and rate-limit cases were
confirmed to fail against the pre-fix code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(admin): implement visual theme cards, album search, and system status diagnostics
* fix(admin): resolve type-checking build errors in SettingsEditor and status route
---------
Co-authored-by: ralksta <ralksta@users.noreply.github.com>
Add revalidatePath('/', 'layout') calls to gallery save, settings save,
and reload routes. This tells Next.js to purge any cached page responses
so the next browser refresh picks up the new hero images and config.
- Asset Picker: Visual browser for hero images with Favorites tab (shown first)
and All Photos tab. Includes infinite scroll and UUID fallback input for
assets not easily found in the grid.
- Drag & Drop: All lists (hero images, standalone albums, subpage albums,
subpage tiles) are now reorderable via drag handles using @dnd-kit.
- Preview Links: 'Preview Site' button in save bar, '↗ Site' in header, and
per-subpage preview links with URL slug preview shown inline.
- Keyboard Shortcuts: ⌘+S / Ctrl+S to save in both Pages and Settings tabs.
- Unsaved Changes Guard: beforeunload warning prevents accidental data loss.
- New API route /api/admin/assets for browsing Immich assets with pagination
and favorites filter via search/metadata endpoint.
When saving gallery/settings via admin, the config cache was invalidated
but the Immich album cache (which stores resolved title overrides and
descriptions) was not cleared. This meant changes only appeared after
the TTL expired or a manual 'Reload' click.
Now both gallery and settings saves also call immich.invalidateAll()
to flush the album cache, making changes visible on next page load.
a) Admin panel now respects the site's light/dark theme toggle via CSS
custom properties that respond to [data-theme='light'] on <html>.
All hardcoded dark colors replaced with semantic CSS variables.
b) Improved contrast in dark mode: secondary text changed from #666/#555
to #a0a0a0, muted text from #555 to #707070. All text is now clearly
readable against dark backgrounds.
c) Backup system was already implemented in yaml-service.ts (creates
timestamped backups in content/.backups/ before each save, keeps last
10 versions). Now the UI shows a confirmation message that a backup
was created after each successful save.
- Add /api/admin/thumbnail/[id] proxy endpoint for serving Immich thumbnails
- Show album cover thumbnails in AlbumCard components (subpages + standalone)
- Show actual image thumbnails in AlbumPicker modal instead of emoji placeholders
- Show small thumbnail previews for hero image entries
- Add corresponding CSS styles for all thumbnail elements
- Add /admin route with password-protected visual page builder
- Page Builder: manage hero images, standalone albums, subpages, and sections
- Album Picker: browse all shared Immich albums with search and filtering
- Settings Editor: theme, grid, footer, legal, SEO configuration
- YAML service with atomic writes and automatic backups (content/.backups/)
- HMAC-signed admin sessions (24h expiry, HttpOnly cookies)
- API endpoints: /api/admin/{auth,gallery,settings,albums,reload}
- Enable with ADMIN_PASSWORD env var; disabled by default
- invalidateConfigCache() export for hot-reload after saves