The zero-trust input security layer for AI agents. Scan untrusted documents before they reach an LLM — detect hidden prompt-injection content, sanitize it, label its trustworthiness, and enforce policy. External content is data, never authority.
aiitg stands for AI Input Trust Gateway — and every letter is a design decision:
| Letter | Meaning | Why it matters |
|---|---|---|
| AI | The problem space is AI/LLM/Agent | This is security for AI, not generic document tooling |
| Input | We guard the input side | Most AI security focuses on outputs/alignment; the input (untrusted documents) is the attacker's real entry point |
| Trust | We make trust explicit and measurable | A document isn't trusted by default — it earns a safe / caution / dangerous label with evidence |
| Gateway | We sit between the document and the model | Like an email gateway filters mail before it reaches the inbox, aiitg filters content before it reaches the LLM's context |
The philosophy in one line: external content is data, never authority. A document should never be able to instruct an AI — it should only ever be read by an AI, after being checked.
That's also why the tool is deliberately named as a gateway, not a scanner: a scanner reports; a gateway enforces. aiitg doesn't just tell you a document is dangerous — it blocks it, sanitizes it, requires human approval, and audits every decision.
2025–2026 research and real-world incidents repeatedly demonstrated a class of attack: instructions hidden inside documents that humans cannot see, but LLMs read and obey.
- Peer-review manipulation: authors hide prompts in manuscripts to make AI reviewers give top scores (arXiv:2507.06185, 2508.20863, 2509.09912)
- Resume injection: hidden instructions in resumes force AI screeners to "must hire" (arXiv:2605.28999)
- Agent hijacking: hidden text in PDFs/web pages makes AI assistants leak secrets or execute dangerous actions
The document a human sees and the document an LLM reads can be completely different — that's the Human-AI Visibility Gap. This project turns that gap into auditable evidence.
Scan → trust label → sanitize → policy. A document with a hidden zero-width instruction is detected, labeled dangerous, sanitized, and blocked by policy before it can reach an LLM.
Untrusted input (docx/xlsx/xls/pdf/html/pptx)
│
▼
┌───────────────────────────────────────────────┐
│ FormatRegistry → parser → ParsedDocument │
│ (format-agnostic intermediate model) │
│ │
│ Detector chain (7 detectors) │
│ → Evidence list (coordinate-level) │
│ │
│ Sanitizer (strip / redact) │
│ → Safe text for LLM context │
│ │
│ Trust label (safe / caution / dangerous) │
│ Policy engine (allow/quarantine/approval/ │
│ block) │
│ → Decision + audit log + human approval │
└───────────────────────────────────────────────┘
│
▼
Safe LLM/Agent consumption
| Stage | Capability | Interface |
|---|---|---|
| M0 | Hidden content audit — 6 formats × 7 detectors → coordinate-level JSON evidence | aiitg scan |
| M1 | Sanitization (strip/redact) + trust labeling (safe/caution/dangerous) | aiitg sanitize, aiitg trust |
| M2 | Policy enforcement (allow/quarantine/human_approval/block) + audit + human-approval queue + MCP server for agent frameworks | aiitg policy, aiitg audit, aiitg approvals, aiitg-mcp |
| ID | Name | Detects | Severity |
|---|---|---|---|
| DET-001 | zero_width | Zero-width / invisible Unicode (U+200B, U+2060, U+FEFF…) | HIGH |
| DET-002 | hidden_style | White text, transparency, display:none, w:vanish |
HIGH |
| DET-003 | tiny_font | Extremely small font (≤2pt) | MEDIUM |
| DET-004 | hidden_sheet | Hidden sheets/rows/columns (with data) in xlsx/xls | MEDIUM |
| DET-005 | ooxml_nodes | OOXML hidden nodes (tracked-delete, altChunk, comments) | MEDIUM |
| DET-006 | annotations | Word comments, PDF annotations, HTML comments | LOW |
| DET-007 | document_meta | Metadata / VBA macros / JS signals | LOW |
docx · xlsx · xls (legacy) · pdf · html · pptx
uv venv .venv && uv pip install -e ".[dev]"
# or
python3.11 -m venv .venv && .venv/bin/pip install -e ".[dev]"aiitg scan report.docx --format json # JSON evidence report
aiitg scan report.xlsx --min-severity high # only high+ findings
aiitg scan report.pdf --format rich # terminal table
aiitg scan ./inbox --recursive --jsonl # batch directory scan, one compact JSON object per line
aiitg list-detectors # list all 7 detectorsExit codes: 0 = clean · 1 = findings at/above threshold · 2 = usage error · 3 = parse error (CI-friendly).
aiitg sanitize report.docx # strip hidden content → safe text
aiitg sanitize report.docx --mode redact # replace with [REDACTED]
aiitg trust report.docx # safe / caution / dangerousaiitg policy report.docx --format rich # allow / quarantine / human_approval / block
aiitg policy report.docx --audit audit.jsonl
aiitg audit audit.jsonl --format rich # append-only JSONL audit trail
aiitg approvals queue.jsonl # list pending approvals
aiitg approvals queue.jsonl --action approve --id <id>aiitg-mcp # stdio transport (Claude Code / Codex / OpenCode)
aiitg-mcp --transport http # streamable HTTPAgents call policy_file before feeding untrusted content into context; anything non-allow gets blocked/sanitized/human-approved.
from aiitg import process_file
result = process_file("report.docx")
if result.is_blocked:
human_review(result.report) # escalate to approval queue
elif result.decision.action.value == "quarantine":
llm_context = result.sanitized.text # sanitized text is safe
else:
llm_context = result.sanitized.text # allow- External content is data, never authority. Documents are parsed, sanitized, and policy-checked before ever becoming instructions.
- Assume compromise. Detection is never 100%; isolation + least privilege + evidence + human approval + audit are the real defense.
- Detector/format decoupling. Detectors consume a format-agnostic
ParsedDocument; new format = new parser, new attack = new detector. - Coordinate-level evidence. Every finding carries exact location (paragraph/run/sheet/row/page/char_range) for forensics and sanitization.
- Conservative trust caps. Any evidence of deliberate concealment can never yield
safe; HIGH/CRITICAL concealment can never yield better thandangerous.
- arXiv:2507.06185 — Hidden Prompts in Manuscripts Exploit AI-Assisted Peer Review
- arXiv:2508.20863 — Misleading LLMs in Peer-Reviewing via Hidden Prompt-Injection
- arXiv:2509.09912 — When Your Reviewer is an LLM: Prompt Injection Risks in Peer Review
- arXiv:2605.28999 — Real-World Prompt-Injection Attacks in LLM-based Resume Screening
make test # 105 tests
make lint # ruff
make typecheck # mypy
make build # build wheel/sdist
make demo # generate and scan a temporary malicious sampleMalicious test fixtures are generated in code (never committed as binaries) — reproducible, auditable, diff-friendly.
- M0 — Hidden content audit (6 formats × 7 detectors → coordinate-level evidence)
- M1 — Sanitization + trust labeling (scan → sanitize → label closed loop)
- M2 — Policy enforcement + audit + human approval + MCP server (agent gateway)
- More formats (legacy
.doc,.ppt, images via OCR) · multi-policy engine · distributed audit · benchmark dataset for hidden-injection detection
MIT
