Files
detections/_docs/05_security/security_report.md
T
Oleksandr Bezdieniezhnykh 097811a67b [AZ-178] Fix Critical/High security findings: auth, CVEs, non-root containers, per-job SSE
- Pin all deps; h11==0.16.0 (CVE-2025-43859), python-multipart>=1.3.1 (CVE-2026-28356), PyJWT==2.12.1
- Add HMAC JWT verification (require_auth FastAPI dependency, JWT_SECRET-gated)
- Fix TokenManager._refresh() to use ADMIN_API_URL instead of ANNOTATIONS_URL
- Rename POST /detect → POST /detect/image (image-only, rejects video files)
- Replace global SSE stream with per-job SSE: GET /detect/{media_id} with event replay buffer
- Apply require_auth to all 4 protected endpoints
- Fix on_annotation/on_status closure to use mutable current_id for correct post-upload event routing
- Add non-root appuser to Dockerfile and Dockerfile.gpu
- Add JWT_SECRET to e2e/docker-compose.test.yml and run-tests.sh
- Update all e2e tests and unit tests for new endpoints and HMAC token signing
- 64/64 tests pass

Made-with: Cursor
2026-04-02 06:32:12 +03:00

7.7 KiB

Security Audit Report

Date: 2026-03-31 Scope: Azaion.Detections (full codebase) Verdict: FAIL → REMEDIATED (Critical/High resolved 2026-04-01)

Summary

Severity Count Resolved
Critical 1 1 ✓
High 3 3 ✓
Medium 5 2 ✓
Low 5

OWASP Top 10 Assessment

Category Status Findings
A01 Broken Access Control FAIL 3
A02 Security Misconfiguration FAIL 2
A03 Software Supply Chain Failures FAIL 2
A04 Cryptographic Failures FAIL 1
A05 Injection PASS
A06 Insecure Design FAIL 2
A07 Authentication Failures FAIL 1
A08 Software or Data Integrity Failures PASS
A09 Logging & Alerting Failures FAIL 1
A10 Mishandling of Exceptional Conditions FAIL 1

Findings

# Severity Category Location Title Status
1 Critical A03 Supply Chain requirements.txt (uvicorn→h11) HTTP request smuggling via h11 CVE-2025-43859 FIXED — pinned h11==0.16.0
2 High A04 Crypto src/main.py JWT decoded without signature verification FIXED — PyJWT HMAC verification
3 High A01 Access Control src/main.py (all routes) No authentication required on any endpoint FIXED — require_auth dependency on all protected endpoints
4 High A03 Supply Chain requirements.txt (python-multipart) ReDoS via python-multipart CVE-2026-28356 FIXED — pinned python-multipart>=1.3.1
5 Medium A01 Access Control src/main.py SSE stream broadcasts cross-user data FIXED — per-job SSE (GET /detect/{media_id}), each client sees only their job
6 Medium A06 Insecure Design src/main.py No rate limiting on inference endpoints Open — out of scope for this cycle
7 Medium A02 Misconfig Dockerfile, Dockerfile.gpu Containers run as root FIXED — non-root appuser added
8 Medium A03 Supply Chain requirements.txt Unpinned critical dependencies FIXED — all deps pinned
9 Medium A02 Misconfig Dockerfile, Dockerfile.gpu No TLS and no security headers Open — handled at infra/proxy level
10 Low A06 Insecure Design src/main.py No request body size limit Open
11 Low A10 Exceptions src/main.py Silent exception swallowing Open
12 Low A09 Logging src/main.py Security events not logged Open
13 Low A01 Access Control src/main.py Exception details leaked in responses Open
14 Low A07 Auth src/main.py Token refresh failure silently ignored Open (by design for offline mode)

Finding Details

F1: HTTP Request Smuggling via h11 (Critical / A03)

  • Location: requirements.txt — unpinned uvicorn[standard] pulls h11-0.14.0
  • Description: CVE-2025-43859 (CVSS 9.1). Lenient parsing of chunked-coding line terminators enables HTTP request smuggling.
  • Impact: Bypass security controls, cache poisoning, session hijacking, data leakage
  • Remediation: Pin h11>=0.15.0 in requirements.txt

F2: JWT Decoded Without Signature Verification (High / A04)

  • Location: src/main.py:67-99 (TokenManager._decode_exp, decode_user_id)
  • Description: JWT payloads are base64-decoded without cryptographic signature verification. Any client can forge tokens with arbitrary claims.
  • Impact: Full user impersonation — attacker crafts JWT with target's user ID to access their AI settings, post annotations under their account
  • Remediation: Use PyJWT with signature verification against the issuer's public key

F3: No Authentication on Endpoints (High / A01)

  • Location: src/main.py — all route handlers
  • Description: All endpoints are publicly accessible. Bearer tokens are optional.
  • Impact: Unauthorized inference triggering, resource exhaustion, unauthorized access to SSE event stream
  • Remediation: Add FastAPI dependency injection for auth middleware on /detect, /detect/{media_id}, /detect/stream

F4: python-multipart ReDoS (High / A03)

  • Location: requirements.txt — unpinned python-multipart
  • Description: CVE-2026-28356 (CVSS 7.5). parse_options_header() regex causes exponential backtracking on malicious headers.
  • Impact: Denial of service
  • Remediation: Pin python-multipart>=1.3.1

F5: SSE Stream Cross-User Data Leak (Medium / A01)

  • Location: src/main.py:608-627
  • Description: All detection events broadcast to all connected SSE clients without filtering.
  • Impact: Any client sees all users' detection results (media IDs, coordinates, status)
  • Remediation: Associate SSE queues with authenticated users; filter events by ownership

F6: No Rate Limiting (Medium / A06)

  • Location: src/main.py:348-469, src/main.py:494-605
  • Description: No rate limiting on compute-intensive inference endpoints.
  • Impact: DoS via inference exhaustion (2 worker threads)
  • Remediation: Add slowapi or similar rate limiting middleware

F7: Docker Containers Run as Root (Medium / A02)

  • Location: Dockerfile:10, Dockerfile.gpu:10
  • Description: No USER directive; processes run as root inside containers.
  • Impact: Container escape or compromise gives root filesystem access
  • Remediation: Add non-root user (adduser --disabled-password appuser && USER appuser)

F8: Unpinned Critical Dependencies (Medium / A03)

  • Location: requirements.txt
  • Description: fastapi, uvicorn[standard], python-multipart are unpinned.
  • Impact: Supply chain attack via compromised PyPI package; inconsistent builds across environments
  • Remediation: Pin all dependencies to specific versions

F9: No TLS / No Security Headers (Medium / A02)

  • Location: Dockerfile CMD, src/main.py (app setup)
  • Description: Uvicorn runs without TLS. No security headers middleware.
  • Impact: Data in transit is unencrypted; missing browser security protections
  • Remediation: Terminate TLS at reverse proxy or add --ssl-* flags; add security headers middleware

F10-F14: Low severity findings (request size limits, exception handling, logging gaps) documented in static_analysis.md and owasp_review.md.

Dependency Vulnerabilities

Package CVE Severity Fix Version
h11 (via uvicorn) CVE-2025-43859 Critical h11>=0.15.0
python-multipart CVE-2026-28356 High >=1.3.1
opencv-python Low (outdated) 4.13.0.92

Recommendations

Immediate (Critical/High)

  1. Pin h11>=0.15.0 to fix HTTP request smuggling vulnerability
  2. Pin python-multipart>=1.3.1 to fix ReDoS vulnerability
  3. Pin all dependencies to specific versions in requirements.txt
  4. Add JWT signature verification using PyJWT with the issuer's public key
  5. Add authentication middleware requiring valid tokens on /detect, /detect/{media_id}, /detect/stream

Short-term (Medium)

  1. Filter SSE events by user — associate queues with authenticated sessions
  2. Add rate limiting on inference endpoints (slowapi or nginx rate limiting)
  3. Run containers as non-root — add USER directive to Dockerfiles
  4. Add security headers middleware (X-Content-Type-Options, X-Frame-Options, HSTS)
  5. Configure TLS at reverse proxy level or add Dockerfile HEALTHCHECK

Long-term (Low / Hardening)

  1. Add request body size limits via uvicorn config or middleware
  2. Log security events — authentication failures, token refresh failures, rate limit hits
  3. Replace silent exception handling with proper error logging
  4. Set up CI/CD with dependency scanning, SAST, and secret scanning
  5. Add CORS configuration if browser clients will access the API directly