fix(cv): isolate document parsing
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.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# 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` `/tmp` tmpfs;
|
||||
- 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.py` and `parser_child.py` passed.
|
||||
- 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_KEY` and `AI_SERVICE_TOKEN` are 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:
|
||||
|
||||
1. Build the hash-locked image and record its digest.
|
||||
2. Confirm the runtime UID is non-root and the root filesystem rejects writes.
|
||||
3. Inspect the applied CPU/memory/PID/capability/tmpfs settings.
|
||||
4. Exercise benign TXT, Markdown, PDF, DOCX and image extraction within the configured budgets.
|
||||
5. Measure peak parent/child memory and OCR duration; lower or evidence any limit increase.
|
||||
6. Run the authenticated browser upload/review journey with synthetic files.
|
||||
7. Canary in production only after explicit authorization; disable CV import rather than removing the boundary if the budget is insufficient.
|
||||
Reference in New Issue
Block a user