Security Audit — Alliex Platform
Date: 2026-04-19 | Version: 1.4.0 | Auditor: rockymac (Claude Code)
Overall posture: Poor — 3 Critical, 5 High, 8 Medium, 6 Low, 7 Informational
Executive Summary
The platform is operating in a demo/pre-handover state with hardcoded development accounts and unsigned session cookies. Three critical findings require immediate attention before any investor presentation or client handover.
Critical Findings
- C1 — Unsigned Session Cookie (Role Forgery):
admin_sessioncookie is plain JSON with no HMAC. Any client can forge{"role":"ADMIN"}. Fix: Redis-backed session IDs + HMAC-SHA256 with SESSION_SECRET. - C2 — ALLOW_DEV_PARAMS=true in production config: Enables
?state=query parameter spoofing on the merchant dashboard without authentication. Fix: set false in .env.production.example and add deploy.sh abort check. - C3 — Hardcoded password123: Both merchant and admin portals authenticate against plaintext passwords in TypeScript source. No database lookup. Fix: Phase 2 DB auth with bcrypt.
High Findings
- H1 — /api/notify has no auth: Any unauthenticated client can POST and spam Telegram ops channel.
- H2 — X-Playwright-Test header bypasses all security: Trivially exploitable to evade blocklist, probe detection, and scraper checks.
- H3 — Missing
secure: trueon session cookies: One-line fix in session.ts. - H4 — No login rate limiting: Add nginx
limit_reqblocks for /login and /admin/login. - H5 — In-memory IP blocklist lost on restart: Write-through to
blocked_ipsPostgres table; hydrate on startup.
Medium Findings (8)
M1: Update @sveltejs/kit ≥2.57.1 (BODY_SIZE_LIMIT CVE). M2: Capital application has no server-side credit limit cap. M3: Duplicate admin session cookie setters — consolidate. M4: /api/notify accepts arbitrary types without Zod validation. M5: Demo credentials in docs/demo-cheatsheet.md — move out of repo. M6: Umami script not in CSP allowlist. M7: PII in response headers (X-Architect, X-Contact, X-Built-With). M8: Investor page publicly accessible — add auth gate.
Low / Informational (13)
L1: Invalid bcrypt hashes in seed SQL. L2: TOTP secrets in memory only. L3: Ingest processor is a stub. L4: Admin URL in robots.txt. L5: Redis has no requirepass. L6: /health discloses version+contact. I1: CSP unsafe-inline/unsafe-eval. I2: Drupal JSON:API allows unauthenticated writes via nginx proxy. I3: Hardcoded Tailscale IP for Ollama. I5: generateCurrentToken() exported from totp.ts. I6: StrictHostKeyChecking=no in deploy.yml. I7: PgBouncer listens on 0.0.0.0.
Remediation Roadmap
Phase 2 security sprint covers C1–C3 and H1–H5. Full audit report on branch audit/security-2026-04-19.