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.
47 lines
2.5 KiB
Markdown
47 lines
2.5 KiB
Markdown
# 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.
|