7.5 KiB
7.5 KiB
Security Analysis Report
Date: 2026-03-02
Repository: /Users/bedas/Developer/GitHub/dcm
Scope: backend FastAPI API and worker, frontend React app, Docker runtime configuration, and local .env posture.
Executive Verdict
Current state is not production ready.
- Blocking code-level issues exist and should be fixed before production exposure.
- Additional user-dependent deployment risks are present in
.envand runtime defaults. Per request, these are listed as MUST KNOW and not marked as blocking.
Method and Coverage
Performed a read-only static review of:
- API auth, authorization, upload and file handling, routing, settings, and worker pipelines.
- Frontend auth token handling and preview rendering behavior.
- Docker and environment defaults affecting network and secret posture.
- Existing security-focused tests and basic frontend API tests.
Blocking Security Issues (Code-Level)
1) High - No abuse controls on expensive authenticated endpoints
Impact:
- Any authenticated user can repeatedly trigger high-cost operations (upload processing, OCR, summarization, routing, indexing), causing queue saturation, infrastructure exhaustion, and external provider cost abuse.
Exploit path:
- Repeated
POST /api/v1/documents/upload - Repeated
POST /api/v1/documents/{document_id}/reprocess
Evidence:
- Upload endpoint has size limits but no rate/volume quota checks:
backend/app/api/routes_documents.py:665-985. - Reprocess endpoint has no rate/cooldown checks:
backend/app/api/routes_documents.py:958-985. - A Redis rate limiter exists but is currently used for markdown export only:
backend/app/services/rate_limiter.py:16-42andbackend/app/api/routes_documents.py:100-120.
Remediation:
- Add per-user and per-IP rate limiting to upload and reprocess endpoints.
- Add per-user daily/rolling quotas (documents, bytes, reprocess calls).
- Add queue depth backpressure and reject or defer requests when saturated.
- Add alerting for anomalous request and job-enqueue rates.
2) Medium - API docs and schema are exposed by default
Impact:
- Unauthenticated endpoint discovery and contract reconnaissance are easier (
/docs,/redoc,/openapi.json).
Exploit path:
- Remote probing of public API metadata when service is internet-reachable.
Evidence:
- FastAPI app is created with default docs behavior and no production gating:
backend/app/main.py:37.
Remediation:
- Disable docs in production (
docs_url=None,redoc_url=None,openapi_url=None) or - Restrict these routes at reverse proxy / edge to trusted admin networks.
3) Medium - Bearer token stored in browser sessionStorage
Impact:
- Any successful XSS on the frontend origin can steal bearer tokens and replay them.
Exploit path:
- Malicious script execution on app origin reads
sessionStorageand exfiltratesAuthorizationtoken.
Evidence:
- Token persisted in sessionStorage and injected into
Authorizationheader:frontend/src/lib/api.ts:39-42,frontend/src/lib/api.ts:61-67,frontend/src/lib/api.ts:84-95,frontend/src/lib/api.ts:103-112.
Remediation:
- Prefer HttpOnly Secure SameSite cookies for session auth, plus CSRF protection.
- If bearer-in-JS remains, enforce strict CSP, remove inline script execution, and add strong dependency hygiene.
MUST KNOW (User-Dependent, Non-Blocking Per Request)
A) Current .env is development-oriented and exposed beyond localhost
Why this matters:
- Service currently binds to all interfaces and uses development settings, which is unsafe for direct internet exposure.
Evidence:
APP_ENV=development:.env:1HOST_BIND_IP=0.0.0.0:.env:2PUBLIC_BASE_URL=http://...:.env:33- Broad CORS for localhost and LAN host:
.env:34
Action:
- Set production values (
APP_ENV=production, HTTPS base URL, strict CORS, host binding behind hardened reverse proxy).
B) Provider SSRF protections are disabled in active env
Why this matters:
- Allowing HTTP, private network targets, and empty allowlist can permit unsafe outbound model-provider endpoints.
Evidence:
- Active
.env:PROVIDER_BASE_URL_ALLOW_HTTP=true,PROVIDER_BASE_URL_ALLOW_PRIVATE_NETWORK=true,PROVIDER_BASE_URL_ALLOWLIST=[]at.env:29-31. - Compose defaults are permissive if env is not hardened:
docker-compose.yml:55-57,docker-compose.yml:100-102.
Action:
- For production set:
ALLOW_HTTP=false,ALLOW_PRIVATE_NETWORK=false, explicit host allowlist.
C) Sensitive model and payload text logging is enabled in active env
Why this matters:
- Prompt/response and payload text may include confidential document content and credentials, increasing breach impact.
Evidence:
- Active
.envenables both flags:.env:22-23. - Code defaults are safer (
false):backend/app/core/config.py:60-61.
Action:
- Disable in production unless explicitly required for short-term diagnostics.
- Apply strict retention and access controls if temporarily enabled.
D) Redis transport/auth hardening depends on env mode and URL
Why this matters:
- Current env uses
redis://with auto security/tls mode; this is not suitable for untrusted network paths.
Evidence:
- Active
.env:REDIS_URL=redis://...,REDIS_SECURITY_MODE=auto,REDIS_TLS_MODE=autoat.env:10-12. - Strict checks are triggered by production mode when auto is used:
backend/app/core/config.py:157-171.
Action:
- In production use
rediss://,REDIS_SECURITY_MODE=strict,REDIS_TLS_MODE=required.
E) Frontend container runs a development server
Why this matters:
- Vite dev server is not intended as a hardened production serving layer.
Evidence:
- Frontend container command runs
npm run dev:frontend/Dockerfile:20. devscript maps to Vite dev mode:frontend/package.json:7.
Action:
- Build static assets and serve behind a production-grade web server/reverse proxy.
F) Login throttle IP identity depends on proxy topology
Why this matters:
- Throttle identity uses
request.client.host; if a proxy masks client IPs, lockout behavior may be inaccurate.
Evidence:
- IP extraction uses transport client host directly:
backend/app/api/routes_auth.py:32-35.
Action:
- Ensure trusted proxy configuration preserves real client IP semantics before internet deployment.
Validation Commands and Outcomes
Preflight:
command -v git-> passed (/usr/bin/git)git rev-parse --is-inside-work-tree-> passed (true)git status --short-> clean before work
Security-related backend tests:
PYTHONDONTWRITEBYTECODE=1 /Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_security_controls.py-> passed (34 tests)PYTHONDONTWRITEBYTECODE=1 /Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_upload_request_size_middleware.py-> passed (3 tests)PYTHONDONTWRITEBYTECODE=1 /Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_app_settings_provider_resilience.py-> passed (6 tests)PYTHONDONTWRITEBYTECODE=1 /Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_processing_log_retention_settings.py-> passed (5 tests)
Frontend auth-client test:
npm run test(infrontend/) -> passed
Note:
pytestis not installed in/Users/bedas/Developer/Python/global_venv/bin/python, so direct module execution viaunittestentrypoints was used for backend test files.
Residual Risk and Coverage Limits
- No dynamic penetration test was run against a live deployed stack.
- No dependency CVE audit (
pip-audit,npm audit) was run in this turn. - Reverse proxy, firewall, TLS termination, and cloud/network policy were not reviewed.