07. Security & Safety¶
Authentication and authorization¶
Confirmed: no API keys, JWT, session auth, or RBAC in app/main.py / app/api/ocr.py. Anyone who can reach the port can submit, list, download, and delete jobs.
Inferred: intended for trusted LAN / VPN / internal mesh, not public internet.
CORS and network exposure¶
ALLOWED_HOSTSdefaults to*→allow_origins=["*"]with credentials enabled- Binding
HOST=0.0.0.0exposes all interfaces when run as configured
Tenant / workspace isolation¶
Absent. Job IDs are unguessable UUIDs, but GET /ocr/jobs enumerates all jobs on disk. No multi-tenant partitioning.
Upload and file handling¶
| Control | Status |
|---|---|
| Extension allowlist | Yes — images + pdf |
| Content-type sniffing | No |
| Max upload size | Not enforced server-side (UI claims 100MB) |
| Job path safety | UUID4 hex validation before mkdir |
| Filename used for suffix only | Yes — stored as input{suffix} |
Secret management¶
- Provider keys via environment /
.env - LiteLLM reads provider-specific env vars (e.g.
NVIDIA_NIM_API_KEY) - Redis password in local compose; full compose Redis has no password
Model / tool safety¶
Not an agent sandbox. Risks are:
- Sending document pixels/text to third-party APIs (NVIDIA, Sarvam, OpenAI via LiteLLM)
- Local Paddle models keep data on-box when configured that way
- No documented PII redaction or retention policy beyond Redis TTL
Preview XSS¶
HTML results are injected into an iframe via srcDoc (frontend/src/App.tsx). If OCR/HTML contains <script> or event handlers, the browser may execute them in the iframe context (Inferred risk; no sanitizer found).
Audit and traceability¶
- Redis job hashes include timestamps and error strings
- Application logs include job_id in task logs
- No immutable audit log store
Known gaps and hardening opportunities¶
- Add authn (API key or OIDC) and disable unauthenticated list/delete
- Enforce upload size and optionally virus scanning
- Restrict CORS to known frontend origins
- Sanitize or sandbox HTML preview (
sandboxattribute / DOMPurify) - Align Redis auth between compose files
- Disk GC for expired jobs
- Rate limiting on submit
Security interview Q&A¶
Q: Is this production-ready for the public internet?
A: Not as-is — no auth, open CORS, enumerable jobs, unbounded uploads.
Q: How do you protect against path traversal?
A: Job IDs must be UUID4 hex; all paths are under JOBS_DIR/job_id.
Q: Where does document data go?
A: Always to local jobs/; additionally to whichever VLM/OCR provider the selected mode uses.