docs: update security production readiness report

This commit is contained in:
2026-03-01 21:07:49 -03:00
parent 4c27fd6483
commit 32b4589b28

129
REPORT.md
View File

@@ -1,90 +1,97 @@
# Security Production Readiness Report # Security Production Readiness Report
Date: 2026-03-01 Date: 2026-03-02
Repository: /Users/bedas/Developer/GitHub/dcm Repository: /Users/bedas/Developer/GitHub/dcm
Assessment type: Static code/configuration review with local security-test execution Assessment type: Static code and configuration review with targeted local security test execution
## Verdict ## Verdict
Not production ready. Not production ready.
Reason: one blocking, code-level security issue was found. Reason: one blocking, code-level access-control and data-disclosure issue was found.
## Scope ## Preflight Results
- Backend API and worker code in `backend/app` - `command -v git` -> pass (`/usr/bin/git`)
- Frontend auth/API client code in `frontend/src` - `git rev-parse --is-inside-work-tree` -> pass (`true`)
- Runtime/deployment configuration in `.env` and `docker-compose.yml` - `git status --short` -> clean before analysis
## Validation Commands And Outcomes ## Validation Commands And Outcomes
- `command -v git` -> pass - `/Users/bedas/Developer/Python/global_venv/bin/python -m unittest backend/tests/test_security_controls.py` -> pass (32 tests)
- `git rev-parse --is-inside-work-tree` -> pass (`true`) - `/Users/bedas/Developer/Python/global_venv/bin/python -m unittest backend/tests/test_upload_request_size_middleware.py` -> pass (3 tests)
- `git status --short` -> clean working tree before analysis - `/Users/bedas/Developer/Python/global_venv/bin/python -m unittest backend/tests/test_app_settings_provider_resilience.py` -> pass (6 tests)
- `/Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_security_controls.py` -> pass (24 tests)
- `/Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_app_settings_provider_resilience.py` -> pass (6 tests)
- `/Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_processing_log_retention_settings.py` -> pass (5 tests)
- `/Users/bedas/Developer/Python/global_venv/bin/python backend/tests/test_upload_request_size_middleware.py` -> failed to run (import error in test setup)
- `/Users/bedas/Developer/Python/global_venv/bin/python -m pytest ...` -> not runnable in current venv (`No module named pytest`)
## Blocking Security Findings ## Blocking Security Findings
### High: No brute-force protection on authentication login ### High: Non-global catalog presets are exposed to all authenticated users
- Severity: High (blocking) - Severity: High (blocking)
- Why this is blocking: `/api/v1/auth/login` accepts unlimited credential attempts with no per-IP or per-username throttling, no lockout, and no backoff. This leaves credential stuffing and password guessing defenses incomplete for production. - Why this is blocking:
- Impact: online account takeover risk increases substantially when passwords are weak, reused, leaked, or defaulted. - The settings model supports `global_shared` scope for predefined paths and tags, but the user-accessible discovery endpoints return all predefined entries without filtering by this scope.
- Exploit path: repeated automated POST requests to `/api/v1/auth/login` until valid credentials are found. - This breaks intended discoverability boundaries and leaks admin-curated non-global taxonomy metadata to standard users.
- Impact:
- Information disclosure across role boundaries for internal path and tag catalogs.
- Reduced separation between admin-only and user-visible metadata.
- Exploit path:
- Any authenticated non-admin user calls `GET /api/v1/documents/paths` and `GET /api/v1/documents/tags`.
- Endpoint responses include every predefined path or tag value regardless of `global_shared` state.
- Evidence: - Evidence:
- `backend/app/api/routes_auth.py:34` defines login endpoint - `backend/app/api/routes_documents.py:399-403` and `backend/app/api/routes_documents.py:423-427` include all predefined tags and paths.
- `backend/app/api/routes_auth.py:42` to `backend/app/api/routes_auth.py:51` performs auth check and returns 401 only - `backend/app/schemas/settings.py:145` and `backend/app/schemas/settings.py:159` define global discoverability scope.
- `backend/app/api/routes_documents.py:75` to `backend/app/api/routes_documents.py:95` shows rate limiting exists but is applied only to content export, not login - `backend/app/services/app_settings.py:709-710`, `backend/app/services/app_settings.py:730`, `backend/app/services/app_settings.py:758-759`, and `backend/app/services/app_settings.py:779` preserve `global_shared` state in normalized settings.
- `backend/app/services/rate_limiter.py:16` to `backend/app/services/rate_limiter.py:42` contains reusable limiter logic currently not used by auth routes
- Required remediation: - Required remediation:
- add login throttling keyed by username and source IP - Filter predefined entries returned by user-facing discovery endpoints by role and `global_shared`.
- add escalating delay or temporary lockout on repeated failures - Keep full catalog visibility for admins only.
- return a stable error message and status on throttled attempts - Add regression tests for non-admin path/tag discovery with mixed `global_shared` values.
- log and monitor failed auth attempt rates
## Additional Code-Level Findings (Non-blocking)
### Low: One security middleware regression test is currently not executable
- Severity: Low
- Risk: reduced confidence in continued enforcement of upload middleware behavior.
- Evidence:
- `backend/tests/test_upload_request_size_middleware.py` currently errors at import time when run directly in this environment
- Recommendation:
- fix test stubs/import assumptions so this test is runnable in CI and local developer environments
## MUST KNOW User-Dependent Risks (Not Blocking Per Request) ## MUST KNOW User-Dependent Risks (Not Blocking Per Request)
These are deployment/operator-controlled and therefore reported as must-know, not blocking findings. These items are deployment, environment, or proxy dependent and are therefore not marked blocking per request requirements.
1. Environment is set to development posture with broad host binding. ### High: Development-first runtime defaults can be promoted to production if not overridden
- Evidence: `.env:1` (`APP_ENV=development`), `.env:2` (`HOST_BIND_IP=0.0.0.0`) - Evidence:
- Risk: exposed surface and relaxed defaults if used outside isolated development network. - `.env.example:5` (`APP_ENV=development`)
- `.env.example:36-38` (`PROVIDER_BASE_URL_ALLOW_HTTP=true`, `PROVIDER_BASE_URL_ALLOW_PRIVATE_NETWORK=true`, empty allowlist)
- `.env.example:14-16` (`redis://`, `REDIS_SECURITY_MODE=compat`, `REDIS_TLS_MODE=allow_insecure`)
- `.env.example:40-41` (`PUBLIC_BASE_URL` on HTTP, local CORS defaults)
- `docker-compose.yml:56-57`, `docker-compose.yml:64-66`, `docker-compose.yml:101-102`, `docker-compose.yml:106-107`
- Risk:
- Weak outbound provider constraints, plaintext internal transport defaults, and non-production environment posture can persist in live deployments.
2. Bootstrap credentials appear placeholder/weak and must be replaced before live use. ### Medium: Login throttle IP identity depends on proxy trust model
- Evidence: `.env:15`, `.env:17` - Evidence:
- Risk: straightforward credential compromise if unchanged. - `backend/app/api/routes_auth.py:32-35` uses `request.client.host` only.
- Risk:
- Behind reverse proxies, all clients may collapse to proxy IP, increasing lockout abuse and reducing attribution quality.
3. Sensitive log text persistence is enabled in current `.env`. ### Medium: API documentation endpoints are exposed by default
- Evidence: `.env:22`, `.env:23`; code path at `backend/app/services/processing_logs.py:47` and `backend/app/services/processing_logs.py:128` - Evidence:
- Risk: OCR/model prompts, responses, and payload text can be stored and later exposed to admins or backups. - `backend/app/main.py:37` creates `FastAPI(...)` with default docs behavior.
- README explicitly references `/docs` as available.
- Risk:
- Public endpoint inventory and schema visibility in exposed deployments.
4. Provider outbound network controls are permissive in current `.env`. ### Medium: Bearer token is stored in browser `sessionStorage`
- Evidence: `.env:29` to `.env:31` - Evidence:
- Risk: admin-configured provider endpoints can target non-HTTPS/private hosts if account compromise occurs. - `frontend/src/lib/api.ts:41`, `frontend/src/lib/api.ts:61-67`, `frontend/src/lib/api.ts:84-94`
- Risk:
- Any successful frontend XSS can exfiltrate active session tokens.
5. Public base URL is HTTP and CORS includes LAN origin. ### Low: Typesense transport defaults to HTTP on internal network
- Evidence: `.env:33`, `.env:34` - Evidence:
- Risk: transport security and origin trust are weaker than production HTTPS allowlist posture. - `docker-compose.yml:66-67`, `docker-compose.yml:107-108`
- Risk:
- Acceptable for isolated local networks, but not suitable for untrusted or cross-host network links.
6. Redis transport is non-TLS in current env posture. ## Security Controls Confirmed Present
- Evidence: `.env:10` to `.env:12` - Login brute-force throttling with lockout and Retry-After handling.
- Risk: acceptable for isolated local stack, unsafe for untrusted networks. - Owner-scoped access checks for non-admin document operations.
- Provider base URL validation with allowlist and DNS revalidation hooks.
- Upload request size and archive extraction guardrails.
- Processing log redaction and metadata-only persistence defaults.
7. Compose defaults are development-first for several sensitive controls. ## Coverage Limits
- Evidence: `docker-compose.yml:40`, `docker-compose.yml:52`, `docker-compose.yml:53`, `docker-compose.yml:60`, `docker-compose.yml:68` - No dependency CVE audit was executed in this run.
- Risk: if overrides are missed, deployment may run with weaker network and provider policies. - This report is based on repository code, configuration templates, and available local tests.
## Production Decision ## Production Decision
Current state is not production ready due to the blocking auth brute-force gap. Current state is not production ready because of the blocking catalog discoverability exposure.
After fixing the blocking issue, production readiness still depends on secure operator configuration of `.env` and runtime network perimeter. After remediating that issue, production readiness still depends on strict deployment choices for environment variables, proxy trust configuration, TLS, and frontend hardening.