19c5251612
Run untrusted document decoders in a secret-free, resource-bounded child process and terminate its process tree on deadline. Harden the production container and enforce parser and lint gates in CI.
2.5 KiB
2.5 KiB
SEC-007 parser isolation verification
Implemented boundary
- The FastAPI web process reads at most 5 MiB and performs cheap extension, signature and DOCX-container preflight checks.
- TXT, Markdown, PDF, DOCX and image decoding runs in
parser_child.py, never in the web process. - Only one parser child is admitted at a time; excess work receives a stable busy response instead of building an in-memory parser queue.
- The child receives a minimal environment without AI provider keys or the service token.
- Linux applies CPU, address-space, output-file, open-file and core-dump limits before importing parser libraries.
- The parent enforces a 25-second deadline and terminates the process group/tree, including OCR descendants.
- Per-request work uses an owner-private temporary directory. Old
work-*directories are reconciled without following symlinks or removing unrelated paths. - The backend has no PDF/DOCX/image fallback. Stable messages replace unexpected internal exceptions and paths.
Container boundary
The production Compose definition resolves the AI service with:
- non-root Dockerfile user;
- read-only root filesystem;
- all Linux capabilities dropped;
no-new-privileges;- 96 PID, 2 CPU and 2 GiB memory limits;
- 768 MiB
noexec,nosuid,nodev/tmptmpfs; - one writable named volume only for the Hugging Face model cache.
Local proof
- Parser tests: 37/37 passed.
- Focused backend extraction/operation tests: 51/51 passed.
- Full backend: 719/719 passed.
- Python compilation:
app.pyandparser_child.pypassed. - Compose config: valid with all intended controls present.
- Timeout regression spawns a harmless sleeping descendant and proves the process tree is gone after the deadline.
- Environment regression proves
GEMINI_API_KEY,GROQ_API_KEYandAI_SERVICE_TOKENare absent from the child.
Remaining external proof
Docker Desktop's Linux daemon is offline, so the image could not be built or run. Before activation:
- Build the hash-locked image and record its digest.
- Confirm the runtime UID is non-root and the root filesystem rejects writes.
- Inspect the applied CPU/memory/PID/capability/tmpfs settings.
- Exercise benign TXT, Markdown, PDF, DOCX and image extraction within the configured budgets.
- Measure peak parent/child memory and OCR duration; lower or evidence any limit increase.
- Run the authenticated browser upload/review journey with synthetic files.
- Canary in production only after explicit authorization; disable CV import rather than removing the boundary if the budget is insufficient.