Skip to content

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_HOSTS defaults to *allow_origins=["*"] with credentials enabled
  • Binding HOST=0.0.0.0 exposes 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

  1. Add authn (API key or OIDC) and disable unauthenticated list/delete
  2. Enforce upload size and optionally virus scanning
  3. Restrict CORS to known frontend origins
  4. Sanitize or sandbox HTML preview (sandbox attribute / DOMPurify)
  5. Align Redis auth between compose files
  6. Disk GC for expired jobs
  7. 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.