| Vulnerability | Attack vector | Impact | Proposed fix | Severity | Priority |
|---|---|---|---|---|---|
| Plaintext passwords in request logs A09 · logger.ts |
Logger serializes full req.body; /auth/login & /auth/register bodies (incl. password) written to every log sink. |
Mass credential compromise via log access (files, CloudWatch, 3rd-party aggregators, support staff). | Remove body from serializer; add pino redact for password, token, authorization. Log only method/url/status. |
critical | P1 |
| Webhook secret & headers logged A09 · leonardo-webhook.ts |
Handler logs JSON.stringify(req.headers) and the raw bearer token on every call. |
Webhook secret leaks → forged callbacks (trigger image-gen / report flows), token replay. | Delete both baseLogger.info lines; at most log a SHA-256 prefix at debug level. |
critical | P1 |
| No brute-force protection on auth A07 · ratelimit.ts |
Single global 100/15min limit; /auth/login open to credential stuffing. In-memory store resets on restart & is per-process. |
Account takeover via password guessing; limiter ineffective once horizontally scaled (compose runs api+worker). | Add a strict per-IP+per-account authLimiter (e.g. 5–10/15min) on /auth/*; move store to Redis (rate-limit-redis). |
high | P2 |
| Weak/default webhook auth (HLS) A07 · hook-hls.ts |
Secret defaults to public 'default_hook_secret_key'; compared with non-constant-time !==. |
If prod env unset, anyone can forge HLS completion callbacks; timing side-channel on the compare. | Require HOOK_SECRET_KEY (no default, min(32)); use crypto.timingSafeEqual; prefer HMAC of payload over static secret. |
high | P2 |
| Upload content-type spoofing A04/A08 · multer.ts |
Validation trusts client file.mimetype; videos reach ffmpeg with no magic-byte check. |
Malicious/oversized payloads stored in R2; potential parser abuse; storage cost abuse. | Verify real type from buffer (file-type), enforce extension allowlist, serve R2 from non-executable path, keep 20MB cap. |
medium | P3 |
| Missing feed composite index PERF · schema.prisma |
Feed query filters isDeleted/isHidden/visibility + sorts createdAt DESC,id DESC with no covering index. |
Full scan + filesort as posts grows → slow feed, high DB CPU, p95 latency spikes. |
Add @@index([isDeleted, isHidden, visibility, createdAt, id]); verify with EXPLAIN before/after. |
medium | P3 |
| Counter drift (non-transactional) INTEGRITY · follower.service.ts |
Follow-state write and followersCount +/- are separate DB calls. |
Permanent desync of denormalized counts on partial failure; wrong follower numbers shown to users. | Wrap state-change + counter in transactionService.doInTransaction (pattern already used in post create). |
medium | P3 |
| CORS wildcard allowed A05 · cors.ts |
CORS_ORIGIN='*' is a supported config; permissive if used in prod. |
Any origin can call the API from a browser context (impact bounded — header-based auth, no cookies). | Disallow '*' when NODE_ENV==='production'; require explicit origin allowlist. |
medium | P3 |
| JWT secret floor + unpinned algo A02 · jwt.service.ts |
JWT_SECRET allowed at 1 char; verify() doesn't pin algorithms. |
Weak-secret brute force; defense-in-depth gap vs algorithm-confusion. | z.string().min(32); pass { algorithms:['HS256'] } to jwt.verify. |
low | P4 |
| No observability / attack detection A09 · cross-cutting |
No metrics, tracing, error tracking, or request-correlation IDs; health check doesn't probe Redis/queues. | Attacks & outages invisible until users complain; slow incident response. | Add request-ID middleware, /metrics (prom-client), Sentry, and a real /health/ready dependency probe. |
low | P4 |
req.body from the logger + add pino redact. (kills the credential-leak path)leonardo-webhook.ts.dev; no schema/runtime contract change.authLimiter on /auth/*; migrate global limiter to Redis store.HOOK_SECRET_KEY required (no default) + timingSafeEqual.EXPLAIN diff).'*' in prod.Severity model — critical: directly exposes credentials/secrets, trivially exploitable · high: realistic account-takeover or scale-breaking abuse vector · medium: exploitable under specific conditions or degrades correctness/performance at load · low: defense-in-depth & operational hygiene. No SQL-injection, RCE, or production stack-trace leakage was found.