Skip to content

Security: Vikaskum77/AI-Risk-Manager

Security

docs/security.md

Step 23 security hardening

Step 23 hardens the existing AI Risk Manager path. It does not create a second identity system, risk engine, device table, model registry, or audit sink.

Identity and authorization

Bearer access tokens are short-lived JWTs. Refresh tokens are rotated and stored only as SHA-256 digests. Argon2id verifies passwords, including a dummy hash path for unknown users so login failures do not disclose whether a username exists. Invalid, expired, wrong-type, and tampered tokens return a generic 401 response.

The additive role vocabulary is USER, ANALYST, SECURITY_ADMIN, ML_ADMIN, and SYSTEM_ADMIN. Legacy Step 16 roles remain valid for compatibility. USER has no administration authority. Model approval, promotion, and rollback are protected by the model-operator dependency; ML_ADMIN, SECURITY_ADMIN, and SYSTEM_ADMIN are authorized alongside the legacy operator roles. User administration and device trust changes are security-operator operations.

Abuse, replay, and input controls

  • Login attempts are limited by username/IP, with Redis sharing the window across workers and a bounded local fallback.
  • API requests are limited by IP and by a hash of the bearer token. Sensitive mutations have a separate configurable limit. 429 responses include Retry-After.
  • Login-event Idempotency-Key handling remains durable in PostgreSQL and returns the original assessment for a valid duplicate. Sensitive operator mutations also reserve explicit Idempotency-Key or client request IDs in Redis with a TTL; a reuse is rejected as 409 Replay detected.
  • Request IDs are returned in X-Request-ID. Body size, timestamp, IP, finite-feature, enum, range, and unknown-field validation happen before risk processing. Clients cannot provide risk_score, risk_level, or decision; those fields are server output and extra fields are rejected.
  • Failed login, brute-force, credential-stuffing, replay, rate-limit, authorization, invalid-input, model-tamper, MFA, and device-trust signals use bounded Prometheus labels and are written to the existing audit path where a durable request context exists.

Device trust and risk integrity

The existing devices table now carries the additive server-managed states KNOWN, NEW, SUSPICIOUS, and BLOCKED. Registration always starts at NEW; clients cannot set trust state. A security operator can change it with PATCH /api/v1/devices/{device_id}/trust. Blocked devices are rejected at login-event ingestion. Risk scores, decisions, and explanations continue to come from the existing rule, supervised, anomaly, and feature-explanation pipeline. No client-supplied score is merged into an assessment.

The Step 22 lifecycle registry remains the only source of the active supervised model. Runtime loading checks lifecycle status, approval, feature_version, artifact existence, and SHA-256 checksum before use. Tampered artifacts fail closed and model-management operations are audited.

Secrets, dependencies, and deployment

.env is ignored and must contain deployment-specific secrets. Compose now requires database and Grafana passwords from that ignored file instead of shipping credential defaults. The checked-in .env.example contains blank placeholders only; set database, JWT, Redis, bootstrap, and Grafana credentials in any shared environment. Application logs and audit metadata redact passwords, tokens, cookies, API keys, JWT material, and bootstrap secrets. SQL access uses SQLAlchemy parameter binding.

Local Compose keeps PostgreSQL, Redis, Kafka, Prometheus, Grafana, and the API bound to loopback by default. Redis supports the optional local REDIS_PASSWORD Compose setting, is not a public service, and all replay, abuse, risk-cache, and state keys use explicit TTLs. Before production, require Redis authentication plus TLS or a private network ACL, disable public port publishing, rotate credentials, and verify eviction/availability policy.

Local Kafka intentionally remains a single-node PLAINTEXT development broker. Production deployment requires private listener exposure, TLS, SASL or mTLS client authentication, broker ACLs for login/risk/security/dead-letter topics, least-privilege consumer groups, encryption at rest, and monitored retention. Those production controls are documented here without changing the local Docker workflow.

Monitoring and verification

The Grafana security dashboard carries an AI SECURITY OVERVIEW panel and includes login volume/failures, blocked logins, MFA, suspicious devices, rate-limit violations, authorization failures, abuse signals, replay detection, and a bounded security-event timeline. Prometheus exports no user IDs, IPs, tokens, request IDs, model versions, or raw request contents as labels.

The Step 23 regression suite covers unauthenticated 401, wrong-role 403, authorized role success, 429 rate limiting, invalid input, replay, model integrity failure, unauthorized promotion, client-decision rejection, brute-force detection, new-device handling, and blocked-device handling.

There aren't any published security advisories