1
0
Fork 0

docs(pdf): concede .pdf as a deliberate design boundary (Session F1)

Reframe .pdf from a 'known gap'/TODO to a deliberate concession across the
honest-limits and OKF-upload docs. A top-level .pdf drop is already refused as
an unsupported format (inbox_frontend.py raises on the else branch), not
half-scanned; adding a PDF parser + reportlab (solely to author white-on-white
test fixtures) is disproportionate for a dev-scoped showcase, and the OCR /
font-render stego carriers a PDF would smuggle are out of scope regardless.

- README honest-limits: .pdf = concession, not TODO; only the numeric CSV FP
  remains a known gap.
- docs/PLAN.md: upload table .pdf row marked 'conceded'; honest-scope paragraph
  names .pdf; assertions tightened to 'every accepted format'.

Closes the last format gap before v1.0 freeze (Session G). No code touched;
357 tests green.
This commit is contained in:
Kjell Tore Guttormsen 2026-07-15 10:15:39 +02:00
commit 66f3cbf4f5
2 changed files with 15 additions and 7 deletions

View file

@ -172,9 +172,13 @@ that a green scan means safe content:
needing OCR, font/render steganography, and encrypted / password-protected files
— the binary layer needs a separate scanner. The front-end owns the container
threats it *can* see (zip-slip → path gate, zip-bomb → size cap, symlink
refusal, CSV/XLSX formula-lead cells). Known gaps: `.pdf` extraction, and the
numeric `-`/`+` CSV false positive (an XLSX numeric cell is typed, so it does not
trip the gate).
refusal, CSV/XLSX formula-lead cells). **`.pdf` is a deliberate concession, not a
TODO:** a top-level `.pdf` drop is *refused as an unsupported format* rather than
half-scanned, because a PDF parser (plus `reportlab` solely to author white-on-white
test fixtures) is disproportionate for a dev-scoped showcase, and the OCR /
font-render stego carriers a PDF would smuggle are already out of scope above. The
one remaining known gap is the numeric `-`/`+` CSV false positive (an XLSX numeric
cell is typed, so it does not trip the gate).
- **Lexicon findings are deduplicated by pattern id**`count=1` and the first
offset are reported, so the same class matched across several channels/variants
collapses to one finding at its first location. This keeps reports readable, but

View file

@ -294,21 +294,25 @@ hides — the place a human does not look):
| `.docx` | injection in a **comment / hidden (vanish) run / core metadata property** | guard scan of extracted text |
| `.xlsx` | **formula injection** (`=cmd\|'…'`, `=HYPERLINK(…)`) + **hidden sheet / cell comment** | front-end + guard |
| `.pptx` | injection in **speaker notes / off-slide text box / image alt-text** | guard scan |
| `.pdf` | injection in extracted / **white-on-white** text | guard scan |
| `.pdf` | injection in extracted / **white-on-white** text | **conceded** — refused as an unsupported format, not extracted (see honest-scope below) |
| `.csv` | formula injection (`=`, `+`, `-`, `@` lead) | front-end + guard |
| **folder** | the OKF bundle-directory shape directly; one member path trips the path gate (T4) | guard |
| **`.zip`** | **zip-slip** entry `../../x.md` (maps straight onto OKFPathError, T4) + **zip-bomb** (bounded by the size cap / a safe-extract limit, LLM10) + symlink entry | front-end + guard |
**Assertions:** each planted vector is caught at the correct stage; the front-end
refuses zip-slip / zip-bomb / oversize fail-fast; the guard rejects
injection/carrier/frontmatter/resource/link/path; a **clean** file of every format
admits (WARN). Detach-proof at **both** stages.
injection/carrier/frontmatter/resource/link/path; a **clean** file of every
*accepted* format admits (WARN). Detach-proof at **both** stages.
**Honest scope for uploads (must be conceded — README honest-limits).** What
survives text extraction is **out of scope**: VBA/macros (`.docm`/`.xlsm`/`.pptm`),
OLE / embedded objects, image-embedded instructions that need OCR, font/render
steganography, and encrypted/password-protected files. The guard scans *extracted
text*; binary-layer carriers need a separate scanner. A high-untrust, unattended
text*; binary-layer carriers need a separate scanner. **`.pdf` is conceded as a
format:** a top-level `.pdf` drop is refused as unsupported rather than extracted,
since a PDF parser + `reportlab` (fixtures only) is disproportionate for a dev-scoped
showcase and its OCR / font-render stego carriers are out of scope regardless. A
high-untrust, unattended
inbox is exactly where assuming uncovered-coverage is most dangerous (§4.7), so the
concession is itself a control.