From 896ab4034a202058d4d5b7dc4c69aaf5f38e4997 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Mon, 6 Jul 2026 10:18:43 +0200 Subject: [PATCH] =?UTF-8?q?docs(plan):=20showcase=20covers=20realistic=20u?= =?UTF-8?q?pload=20formats=20=E2=80=94=20two-stage=20extract=E2=86=92guard?= =?UTF-8?q?,=20dev-scoped=20parsers,=20honest=20binary-layer=20limits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/PLAN.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/PLAN.md b/docs/PLAN.md index ae2e6dc..50504d4 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -244,6 +244,53 @@ prove intent, not to coincidentally pass. — semantic/factual poisoning stays out (README honest-limits), consistent with the core showcase. +#### Realistic upload formats — the two-stage inbox (extract → materialize → guard) + +A human inbox does not receive tidy `{path: text}` dicts; it receives the files +people actually drop: `.txt`, `.md`, Word `.docx`, Excel `.xlsx`, PowerPoint +`.pptx`, `.pdf`, `.csv`, whole **folders**, and **`.zip`** archives. The showcase +therefore has two stages, honouring the locked text-extraction boundary (§ +"Text-extraction boundary"): the guard core never grows a file parser. + +1. **Extract & materialize (the inbox front-end).** Reads each dropped file, walks + folders, and *safely* unpacks archives; extracts text via format libraries + (`python-docx`, `openpyxl`, `python-pptx`; stdlib `zipfile`/`csv`); materializes + the result into an OKF bundle `{concept_path: text}` with provenance + (`origin=EXTERNAL`, source filename + type). **This stage owns the container and + format threats.** These libraries are **showcase/dev-scoped only** — never core + `dependencies` (which stays `[]`). Promotion to an optional `[extract]` extra is + a documented future option if a consumer wants turnkey extraction, not v1. +2. **Guard (`import_bundle`).** Scans every extracted concept + the OKF structural + gates → aggregate disposition. **This stage owns the text/structural threats.** + +**One representative planted vector per format** (the point is where the payload +hides — the place a human does not look): + +| Input | Hidden vector planted | Caught at | +|---|---|---| +| `.txt` | raw injection + carrier (zero-width / homoglyph / rot13 / base64) | guard scan | +| `.md` | OKF frontmatter attack (T2) + body injection (T1) | guard | +| `.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 | +| `.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. + +**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 +inbox is exactly where assuming uncovered-coverage is most dangerous (§4.7), so the +concession is itself a control. + **Deferred, unchanged:** T5b/B (the persisted cross-run link graph) waits for a consumer that owns corpus storage; §7.2 dormant cross-run links remain a documented residual until then.