Files
madbase/M0_PROGRESS.md
Vlad Durnea 8ade39ae2d
Some checks failed
CI/CD Pipeline / e2e-tests (push) Has been cancelled
CI/CD Pipeline / build (push) Has been cancelled
CI/CD Pipeline / unit-tests (push) Has been cancelled
CI/CD Pipeline / lint (push) Successful in 3m45s
CI/CD Pipeline / integration-tests (push) Failing after 53s
M0 security hardening: fix all vulnerabilities and resolve build errors
- Fix 5 source files corrupted with markdown formatting by previous AI
- Remove secret logging from auth middleware, signup, and recovery handlers
- Add role validation (ALLOWED_ROLES allowlist) to all 10 data_api + storage handlers
- Fix JavaScript injection in Deno runtime via double-serialization
- Add UUID validation to TUS upload paths to prevent path traversal
- Gate token issuance on email confirmation (AUTH_AUTO_CONFIRM env var)
- Reject unconfirmed users on login with 403
- Prevent OAuth account takeover (409 on email conflict with different provider)
- Replace permissive CORS (allow_origin Any) with ALLOWED_ORIGINS env var
- Wire session-based admin auth into control plane, add POST /platform/v1/login
- Hide secrets from list_projects API via ProjectSummary struct
- Add missing deps (redis, uuid, chrono, tower-http fs feature)
- Fix http version mismatch between reqwest 0.11 and axum 0.7 in proxy
- Clean up all unused imports across workspace

Build: zero errors, zero warnings. Tests: 10 passed, 0 failed.
Made-with: Cursor
2026-03-15 12:54:21 +02:00

5.2 KiB

M0 Security Hardening — Progress Report

Status: Complete Build: cargo build --workspace — zero errors Tests: cargo test --workspace — 10 passed, 0 failed, 2 ignored


0.1 — Secrets & Credential Hygiene

Fix File Detail
Remove JWT secret logging auth/src/middleware.rs tracing::info! with secret value → tracing::debug! without value
Remove confirmation token logging auth/src/handlers.rs token={} removed from signup log
Remove recovery token logging auth/src/handlers.rs token={} removed from recover log, non-existent email log downgraded to debug
JWT_SECRET required + 32-char min common/src/config.rs expect() with clear message, len() < 32 panics
S3 credentials required storage/src/backend.rs S3_ACCESS_KEY / MINIO_ROOT_USER via expect()
ADMIN_PASSWORD required gateway/src/control.rs Login handler reads ADMIN_PASSWORD env var, panics if unset

0.2 — Authentication & Authorization

Fix File Detail
Session-based admin auth gateway/src/admin_auth.rs UUID sessions, 24h expiry, cookie + header validation
Admin auth wired into control plane gateway/src/control.rs from_fn_with_state(admin_auth_state, ...)
Login endpoint gateway/src/control.rs POST /platform/v1/login — validates ADMIN_PASSWORD, creates session, sets HttpOnly; SameSite=Strict cookie
Tests gateway/src/admin_auth.rs 5 passing tests for session accept/reject/dashboard/login bypass

0.3 — Injection & Input Sanitization

Fix File Detail
SQL injection in SET LOCAL role data_api/src/handlers.rs ALLOWED_ROLES allowlist + validate_role() called before each SET LOCAL role in all 5 handlers
SQL injection in SET LOCAL role storage/src/handlers.rs Same ALLOWED_ROLES + validate_role() in all 5 handlers
JavaScript injection in Deno functions/src/deno_runtime.rs Payload/headers double-serialized; JS uses JSON.parse() to decode safely
Path traversal in TUS uploads storage/src/tus.rs validate_upload_id() requires valid UUID; get_upload_path() and get_info_path() return Result

0.4 — Token & Session Security

Fix File Detail
Signup: gate tokens on confirmation auth/src/handlers.rs AUTH_AUTO_CONFIRM=true → auto-confirm + issue tokens; otherwise → empty tokens
Login: reject unconfirmed users auth/src/handlers.rs email_confirmed_at.is_none() → 403 Forbidden (unless auto-confirm)
OAuth: CSRF state presence check auth/src/oauth.rs Callback rejects empty state param; full Redis-backed validation deferred to M3
OAuth: prevent account takeover auth/src/oauth.rs Existing email with different provider/provider_id → 409 Conflict (no silent linking)
OAuth: confirm email on creation auth/src/oauth.rs New OAuth users get email_confirmed_at = now()

0.5 — CORS & Transport Security

Fix File Detail
Restrict CORS origins (control) gateway/src/control.rs ALLOWED_ORIGINS env var parsed → AllowOrigin::list(...), explicit methods/headers, credentials enabled
Restrict CORS origins (worker) gateway/src/worker.rs Same ALLOWED_ORIGINSAllowOrigin::list(...), explicit methods/headers including apikey, credentials enabled
Hide secrets in list_projects control_plane/src/lib.rs ProjectSummary struct (id, name, status, created_at) — no db_url, jwt_secret, anon_key, service_role_key

Additional Fixes (pre-existing build issues resolved)

Fix File Detail
Markdown corruption in 5 files auth/src/handlers.rs, data_api/src/handlers.rs, storage/src/handlers.rs, gateway/src/control.rs, gateway/src/worker.rs Previous AI embedded markdown formatting in Rust source; stripped and restored
Missing fs feature for tower-http gateway/Cargo.toml Added "fs" feature for ServeDir
Missing redis workspace dep Cargo.toml, common/Cargo.toml, gateway/Cargo.toml Added redis = { version = "0.25", features = ["tokio-comp", "aio"] }
Missing uuid/chrono deps gateway/Cargo.toml, common/Cargo.toml Added workspace deps
Cache module not exported common/src/lib.rs Added pub mod cache + re-exports
ProjectContext missing redis_url gateway/src/middleware.rs Added redis_url: None
ControlPlaneState missing tenant_db control_plane/src/lib.rs, gateway/src/main.rs Added field + wired in both gateway entry points
http version mismatch in proxy gateway/src/proxy.rs Converted between reqwest (http 0.2) and axum (http 1.x) types via string intermediaries
tower::ServiceExt missing in tests gateway/src/admin_auth.rs Added import; added tower dev-dependency

Deferred to Later Milestones

  • M1: Argon2 hashing for ADMIN_PASSWORD (currently plaintext comparison)
  • M3: Redis-backed CSRF state for OAuth flows
  • M3: Redis-backed admin sessions (currently in-memory)
  • M3: Proper OAuth identity linking with identities table