Files
fermata/threat-landscape.svg
2026-05-29 18:19:22 +02:00

72 lines
6.4 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 520" width="720" height="520" font-family="system-ui, -apple-system, sans-serif" font-size="11">
<rect x="0" y="0" width="720" height="520" rx="8" fill="#f8f9fa"/>
<text x="360" y="24" text-anchor="middle" font-size="13" font-weight="bold" fill="#1a1a2e">The Reveal Triangle — why blocking the file is not enough</text>
<!-- Three dimensions -->
<text x="30" y="52" font-size="10" font-weight="bold" fill="#636e72">THREE INDEPENDENT DIMENSIONS</text>
<!-- Read -->
<rect x="30" y="62" width="210" height="68" rx="6" fill="#e8f8f0" stroke="#1e8449" stroke-width="1.5"/>
<text x="40" y="80" font-size="11" font-weight="bold" fill="#1e8449">Read</text>
<text x="40" y="94" font-size="9" fill="#333">Can the agent open a file?</text>
<text x="40" y="107" font-size="9" fill="#888">Operates on file identity</text>
<text x="40" y="120" font-size="9" fill="#1e8449">→ .botignore handles this</text>
<!-- Write -->
<rect x="255" y="62" width="210" height="68" rx="6" fill="#e8f0f8" stroke="#2471a3" stroke-width="1.5"/>
<text x="265" y="80" font-size="11" font-weight="bold" fill="#2471a3">Write</text>
<text x="265" y="94" font-size="9" fill="#333">Can the agent modify a file?</text>
<text x="265" y="107" font-size="9" fill="#888">Operates on file identity</text>
<text x="265" y="120" font-size="9" fill="#2471a3">→ git provides recovery</text>
<!-- Reveal -->
<rect x="480" y="62" width="210" height="68" rx="6" fill="#fdecea" stroke="#c0392b" stroke-width="2"/>
<text x="490" y="80" font-size="11" font-weight="bold" fill="#c0392b">Reveal</text>
<text x="490" y="94" font-size="9" fill="#333">Do secret values enter the LLM?</text>
<text x="490" y="107" font-size="9" fill="#888">Operates on data content</text>
<text x="490" y="120" font-size="9" fill="#c0392b">→ nothing addresses this today</text>
<!-- Independence callout -->
<rect x="30" y="142" width="660" height="24" rx="4" fill="#fff3cd" stroke="#d4a017" stroke-width="1"/>
<text x="360" y="158" text-anchor="middle" font-size="10" fill="#7d6608">These are independent. An agent can have read access to .env without secret values being revealed — if output is redacted.</text>
<!-- How secrets reach the LLM despite file blocking -->
<text x="30" y="190" font-size="10" font-weight="bold" fill="#636e72">HOW SECRETS REACH THE LLM DESPITE FILE BLOCKING</text>
<text x="430" y="190" font-size="9" fill="#888">(from agent behavior research)</text>
<!-- Sophistication gradient -->
<!-- L0: Obvious -->
<rect x="30" y="200" width="330" height="44" rx="6" fill="#e8f8f0" stroke="#1e8449" stroke-width="1"/>
<text x="40" y="216" font-size="10" font-weight="bold" fill="#1e8449">Obvious — caught by file ACL</text>
<text x="40" y="232" font-size="9" fill="#333">cat .env · Read(".env") · cat ~/.aws/credentials</text>
<rect x="370" y="200" width="320" height="44" rx="6" fill="#e8f8f0" stroke="#1e8449" stroke-width="1" stroke-dasharray="4,2"/>
<text x="380" y="216" font-size="9" fill="#1e8449">Blocked by .botignore</text>
<text x="380" y="232" font-size="9" fill="#888">The agent names the file directly. ~90% of cases.</text>
<!-- L2-L3: Indirect value exposure -->
<rect x="30" y="254" width="330" height="56" rx="6" fill="#fef5e7" stroke="#d4a017" stroke-width="1"/>
<text x="40" y="270" font-size="10" font-weight="bold" fill="#7d6608">Indirect — values leak through other tools</text>
<text x="40" y="284" font-size="9" fill="#333">docker-compose config (interpolates .env values)</text>
<text x="40" y="298" font-size="9" fill="#333">printenv · env (shows sourced env vars)</text>
<rect x="370" y="254" width="320" height="56" rx="6" fill="#fdecea" stroke="#c0392b" stroke-width="1" stroke-dasharray="4,2"/>
<text x="380" y="270" font-size="9" fill="#c0392b">File was never read — values still leak</text>
<text x="380" y="284" font-size="9" fill="#888">The secret appears in tool output from a command</text>
<text x="380" y="298" font-size="9" fill="#888">that has nothing to do with the secret file.</text>
<!-- L4: Constructed access -->
<rect x="30" y="320" width="330" height="56" rx="6" fill="#fef5e7" stroke="#d4a017" stroke-width="1"/>
<text x="40" y="336" font-size="10" font-weight="bold" fill="#7d6608">Constructed — agent builds the path indirectly</text>
<text x="40" y="350" font-size="9" fill="#333">cat $CONFIG_FILE · cat $(find . -name '.env*')</text>
<text x="40" y="364" font-size="9" fill="#333">writes a script that reads .env, then runs it</text>
<rect x="370" y="320" width="320" height="56" rx="6" fill="#fdecea" stroke="#c0392b" stroke-width="1" stroke-dasharray="4,2"/>
<text x="380" y="336" font-size="9" fill="#c0392b">Path is hidden from static analysis</text>
<text x="380" y="350" font-size="9" fill="#888">Variable expansion, command substitution, or a</text>
<text x="380" y="364" font-size="9" fill="#888">two-step write-then-execute pattern.</text>
<!-- L6: Exfiltration -->
<rect x="30" y="386" width="330" height="44" rx="6" fill="#f5eef8" stroke="#7f8c8d" stroke-width="1"/>
<text x="40" y="402" font-size="10" font-weight="bold" fill="#7f8c8d">Exfiltration — beyond tool-level defense</text>
<text x="40" y="418" font-size="9" fill="#333">curl -d "$(cat .env)" · git push with secrets</text>
<rect x="370" y="386" width="320" height="44" rx="6" fill="#f0eff4" stroke="#7f8c8d" stroke-width="1" stroke-dasharray="4,2"/>
<text x="380" y="402" font-size="9" fill="#7f8c8d">Needs sandbox / network controls</text>
<text x="380" y="418" font-size="9" fill="#888">Out of scope by design. See sandcage.</text>
<!-- What fermata covers -->
<rect x="30" y="444" width="660" height="64" rx="6" fill="#fff" stroke="#1e8449" stroke-width="1.5"/>
<text x="40" y="462" font-size="10" font-weight="bold" fill="#1a1a2e">fermata's coverage</text>
<rect x="40" y="470" width="10" height="10" rx="2" fill="#e8f8f0" stroke="#1e8449"/>
<text x="56" y="480" font-size="9" fill="#333">PreToolUse — blocks obvious file access (row 1)</text>
<rect x="280" y="470" width="10" height="10" rx="2" fill="#e8f0f8" stroke="#2471a3"/>
<text x="296" y="480" font-size="9" fill="#333">PostToolUse — redacts secret values from all output (rows 13)</text>
<text x="40" y="498" font-size="9" fill="#888">File ACLs solve Read. Secret redaction solves Reveal. Both are needed because they are independent dimensions.</text>
</svg>