A deliberately low-infrastructure workflow. Convert Oracle HCM PDF guides to Markdown with a custom
CLI (pdf2md, now built on IBM Docling), drop the Markdown into a dedicated Obsidian vault
folder, and search it in plain language during ticket triage. The same vault is also read by an AI
layer (PAI on Claude Code) during triage. No embeddings, no vector database, no network service.
The honest read is mostly favorable, with one finding that genuinely moved since the last audit.
The document-conversion step is the sharp edge. Since Docling replaced the old converter, the
toolchain inherited an RCE that fires when Docling deserializes attacker-controlled YAML during
normal parsing. A poisoned PDF, if one ever entered the input/ folder, could execute
code with the converter's privileges. Everything downstream is comparatively well-contained, and two
risks the last audit flagged have since been verified as controls in the owner's favor.
What it is. A three-step personal knowledge workflow, not a service. No listening
port, no database, no multi-user surface. Convert with pdf2md (Docling backend, unpinned;
a FastAPI/uvicorn web UI wraps it; ocrmypdf runs first for the rare scanned PDF), store
the .md in an Obsidian vault folder, then search it manually and via PAI during triage.
What is NOT hardened. The converter parses whatever PDF is placed in
input/; nothing enforces that the file came from Oracle's portal, and Docling runs
unsandboxed with the user's privileges. The vault content then flows into an AI context with the same
indirect-prompt-injection consideration any AI-read corpus carries.
| Function | Control present |
|---|---|
| Govern | Workflow is documented; single-owner, single-machine scope; no third-party data sharing. |
| Identify | This assessment maps the full data flow, trust boundary, and exact toolchain read from real config (requirements.txt, .obsidian/, gs --version). |
| Protect | Zero Obsidian community plugins installed (no .obsidian/plugins/, no community-plugins.json) — the whole community-plugin attack surface is absent; webviewer: false; local Ghostscript 10.07.1 is above the CVE-2024-29510 exploited ceiling; local-only, no network service, no standing secret; Oracle's own PDFs are the intended trusted-origin input. |
| Detect | Thin. No integrity scan of a PDF before conversion; no dependency-vulnerability scan on the pdf2md venv. Obsidian file-recovery is on. |
| Respond | Personal workflow: a bad conversion output is visible in the vault and can be deleted; no auto-propagation. |
| Recover | Source PDFs are re-downloadable from Oracle; vault is re-buildable; core sync on for redundancy. |
Rated after the controls above. Scale: Low / Moderate / High. Control column maps to NIST AI RMF / ISO 42001.
| # | Threat scenario | Vulnerability | Control engaged | Imp. | Lik. | Residual |
|---|---|---|---|---|---|---|
| T1 | Malicious-document RCE in the converter: a poisoned PDF triggers Docling's unsafe-YAML deserialization (CVE-2026-24009) and runs code during conversion. | Docling parses attacker-influenceable input unsandboxed; dependency unpinned; no provenance gate. | ISO 42001 A.6.2.4 / AI RMF MANAGE-2.2 (partial) | High | Low–Mod | HIGH |
| T2 | Ghostscript RCE via the OCR step: a crafted scanned PDF exploits Ghostscript during ocrmypdf. |
ocrmypdf shells out to Ghostscript. | MANAGE-2.2 — mitigated: gs 10.07.1 patched, OCR rarely runs | High | Low | LOW–MOD |
| T3 | Indirect prompt injection: converted text steers PAI during AI triage. | Vault content reaches an AI context. | AI RMF MEASURE-2.7 (OWASP LLM01); trusted corpus + human-reviewed triage | Mod | Low | LOW–MOD |
| T4 | Obsidian community-plugin abuse (PHANTOMPULSE / REF6598): Shell Commands plugin runs code on vault open. | Community plugins are unsandboxed. | ISO 42001 A.6.2.4 — precondition NOT met: zero community plugins | High | Very Low | LOW |
| T5 | Supply-chain compromise of converter deps: a trojanized/vulnerable Docling or transitive package. | Unpinned docling; no dependency scanning. |
MAP-4.1 (OWASP LLM03) — no pin, no scan | High | Low | MODERATE |
| T6 | Data exfiltration: sensitive HCM content leaves the machine. | KB holds Oracle config knowledge, not live employee data; local-only. | PROTECT (CSF) — local, no network sink, no secret | Low | Low | LOW |
| Tool | Known vuln (CVE/KEV) | Recent breach / incident | Exposure here | Options (owner decides) |
|---|---|---|---|---|
| Docling (pdf2md backend) | CVE-2026-24009 — RCE via unsafe PyYAML deserialization: a malicious document runs arbitrary Python during parsing (Oligo Security). Also a path-traversal via tar symlinks (IBM). | Disclosed by Oligo Security (2026). Not on CISA KEV as of 2026-06-30. | EXPOSED Docling is the converter and parses dropped PDFs. The dependency is unpinned, so the installed version is not guaranteed. This is T1 and T5. | (a) Pin Docling to a patched release; (b) convert only trusted-origin PDFs; (c) run the converter in a container / restricted user; (d) add pip-audit to the venv. |
| Ghostscript (via ocrmypdf) | CVE-2024-29510 — format-string RCE, versions ≤ 10.03.0, actively exploited (TuxCare). | Ongoing exploitation of unpatched installs through 2025–2026. | NOT EXPOSED (in-range) local gs is 10.07.1, above the ≤10.03.0 ceiling. Verified control in the owner's favor. OCR also rarely runs. | Keep Ghostscript current (it already is); containerize ocrmypdf if OCR is ever run on untrusted scans. |
| Obsidian | No high-severity core-app RCE CVE applicable to this use found (searched 2026-06-30). The real risk is feature-abuse, not a core CVE. | PHANTOMPULSE / REF6598 (Elastic Security Labs, 2026-04-14): the Shell Commands community plugin weaponized to run code on vault-open. Precondition: victim manually enables community plugin sync. | NOT EXPOSED vault has zero community plugins installed (verified: no .obsidian/plugins/, no community-plugins.json). The PHANTOMPULSE precondition is definitively not met. Verified control in the owner's favor. |
Keep the no-community-plugin posture; if a plugin is ever added, vet it and never enable Shell Commands / Hider on a synced vault. |
| Tesseract (via ocrmypdf) | No actively-exploited RCE applicable to local OCR of trusted PDFs found (searched 2026-06-30). | None material found (searched 2026-06-30). | LOW runs only on the rare scanned PDF; local, trusted input. | Keep current; no action needed. |
| FastAPI / uvicorn (pdf2md web UI) | No in-use CVE found for the pinned ranges (searched 2026-06-30). | None material found. | LOW the web UI binds locally and is not network-exposed. | Keep it bound to localhost; do not expose the converter UI publicly. |
| Pri | Option | Addresses | Tradeoff |
|---|---|---|---|
| P1 | Pin Docling to a patched release and re-pin on a cadence (replace bare docling in requirements.txt). | T1, T5 | Minutes of work; trade "always latest" for "known-good". Right trade for a doc parser. |
| P1 | Convert only PDFs from a trusted origin (Oracle's portal); treat any third-party PDF as untrusted. | T1 | A habit, not a tool-enforced control; pair with P2. |
| P2 | Run the converter in a container or restricted user so a parse-time RCE cannot reach the vault or home directory. | T1, T2 | Adds a step; strongest structural mitigation for an unsandboxed parser. |
| P2 | Add pip-audit (or equivalent) to the pdf2md venv to catch a vulnerable/trojanized dependency. | T5 | One command; catches known-CVE deps, not novel supply-chain. |
| P3 | Keep the vault free of community plugins; if one is ever needed, vet it and avoid Shell Commands/Hider on a synced vault. | T4 | None; documents the posture so it is not weakened later. |
| P3 | Keep the AI-triage step human-reviewed; treat vault text as a corpus to summarize, not instructions to follow. | T3 | Already the default; keeps indirect prompt injection contained. |
The letter moved down from what a surface read would give this tidy little workflow, and it moved for one honest reason: the converter now carries a document-parsing RCE, and a knowledge workflow's whole job is to parse documents. That is the finding worth publishing.