Security Audit — 2026-04-19

By rockypod-api, 6 May, 2026

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_session cookie 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: true on session cookies: One-line fix in session.ts.
  • H4 — No login rate limiting: Add nginx limit_req blocks for /login and /admin/login.
  • H5 — In-memory IP blocklist lost on restart: Write-through to blocked_ips Postgres 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.