Setup
Get your environment running
Two independent paths to the same two scenarios. Run whichever your facilitator points you at — both were run end-to-end against this exact data before this guide was written, not just described.
Section 1 — Kali container, hand-picked skills
One Docker image with tshark/tcpdump/scapy, Claude Code, and the 10 hand-picked skills
baked in at docker build time — see
tailgate/Dockerfile
— instead of live-installing over docker exec.
Prerequisites
- Docker (no local build needed —
docker pullfetches the pre-built image from GHCR). - A
.envfile in thetailgate/folder (copied fromcasky-box/.env) with a workingANTHROPIC_API_KEY:cp ../casky-box/.env tailgate/.env
Same quoted-value bug as TollBooth/OpenDoor: docker run --env-file does
not strip quotes from .env values. Fix once, right after
copying:
sed -i.bak -E 's/^([A-Z_][A-Z0-9_]*)="(.*)"$/\1=\2/' tailgate/.env && rm tailgate/.env.bak
Confirm it worked — should print 1, not 0:
grep '^ANTHROPIC_API_KEY=' tailgate/.env | cut -d= -f2- | grep -c '^sk-ant-'
Steps
# Run every command below from THIS folder (casky-workshops/tailgate/).
# 0. Pull the pre-built image from GHCR (rebuilt nightly with the latest patches) instead
# of building locally — much faster at a live session.
docker pull ghcr.io/casky-ai/casky-tailgate:latest
docker tag ghcr.io/casky-ai/casky-tailgate:latest casky-tailgate
# Fallback, kept for reference — tshark/tcpdump/scapy, Claude Code, and the 10 skills are
# still baked into the image at build time (see Dockerfile); rebuild locally if you're
# iterating on the Dockerfile/skill list itself, or if GHCR is unreachable:
# docker build -t casky-tailgate .
# 1. Start a persistent container with this folder mounted + the shared key available
docker run -d --name casky-tailgate \
--env-file .env \
-v "$(pwd)":/root/tailgate \
casky-tailgate
docker exec casky-tailgate test -f /root/tailgate/verify.sh \
&& echo "[+] mount OK" || echo "[!] wrong directory — re-run from casky-workshops/tailgate/"
# 2. Run ./verify.sh — expect 14/14 PASS.
docker exec -w /root/tailgate casky-tailgate ./verify.sh
# 3. Bash into the container and start Claude Code interactively.
docker exec -it -w /root/tailgate casky-tailgate bash
# ...now inside the container's shell:
export PATH="$HOME/.local/bin:$PATH"
./start.sh # welcome banner + sanity check
claude # drops into an interactive Claude Code session — paste the scenario
# prompt from this wiki's scenario pages and let it work
Tools/Claude Code/skills baked into the image, pulled from GHCR (no docker
login needed, publicly pullable): Claude Code on PATH, 10/10 skills
linked, and a real round-trip against the Anthropic API:
$ claude --print "Reply with exactly the single word: PONG"
PONG
== tooling ==
ok tshark
ok jq
ok tcpdump
== act 1 — initial access (T1566.001, T1078, T1133) ==
PASS malicious attachment hash present across phishing-email.eml/mail-gateway.log/endpoint-alert.log (3)
PASS mail gateway ALLOWED verdict (DMARC p=none let it through) (1)
PASS Valid Accounts (T1078) sign-in event present (1)
PASS External Remote Services (T1133) VPN session event present (1)
== act 2 — lateral movement (T1570, T1021.002, T1021.001) ==
PASS first-time-seen internal host-pair flows (lateral tool transfer signal) (3)
PASS SMB/Admin Shares (T1021.002) logon event present (1)
PASS RDP (T1021.001) logon event present (1)
== act 3 — domain compromise (T1558.003, T1558.004) ==
PASS Kerberoasting TGS burst with RC4 downgrade (T1558.003) (6)
PASS AS-REP Roasting (T1558.004) confirmed NOT exploited — the built-in over-claim check (1)
PASS SPN-registered service accounts with stale passwords (3)
PASS service account with Kerberos preauth disabled (svc-legacyapp) (1)
== guestlist (proactive audit) ==
PASS DMARC p=none finding present (2)
PASS network segmentation findings present (3)
PASS AD-2 correctly labeled probed-not-exploited (matches ad/kerberos-events.txt's NOT FOUND) (1)
----
RESULT: 14 passed, 0 failed
This laptop is READY.
./start.sh (step 3) confirmed too:
[+] lab data present: Act 1-3 evidence (Tailgate) + guestlist/ (GuestList)
[+] agent skills mounted at /root/.claude/skills (10 skills)
[+] Claude Code found.
mode: online (shared key)
Work Tailgate or GuestList inside that interactive Claude Code session (skills already
mounted). exit the claude session and the container shell (two
exits) between attendees, then run
docker exec -w /root/tailgate casky-tailgate ./reset.sh from outside to restore
the data.
Section 2 — Same scenarios, run on Casky Box
The same casky-runner container TollBooth/OpenDoor uses — all 818 skills
mounted read-only, classifier picks the relevant ones from evidence automatically.
Prerequisites
Casky Box running — pulled from GHCR, no separate repo to clone, using its own
.env:
cd ../casky-box # casky-workshops/casky-box, shared by every workshop
cp .env.example .env # first time only — then set ANTHROPIC_API_KEY
docker compose pull
docker compose up -d
If already up from earlier, this is a no-op — confirm with docker compose ps.
See casky-box/README.md
for what's in it.
Steps
# Run every command below from THIS folder (casky-workshops/tailgate/).
cd /path/to/casky-workshops/tailgate
test -f phishing-email.eml && echo "[+] correct folder" || echo "[!] cd to casky-workshops/tailgate first"
# 1-3. Evidence is already text (no tshark pre-processing needed, unlike TollBooth's pcap) —
# concatenate each act's files into one bundle per scenario.
{
echo "=== Act 1 - Phishing email (initial access) ==="; cat phishing-email.eml
echo; echo "=== Act 1 - Mail gateway delivery/detonation log ==="; cat mail-gateway.log
echo; echo "=== Act 1 - Endpoint + auth telemetry ==="; cat endpoint-alert.log
echo; echo "=== Act 2 - Internal netflow baseline vs. incident window ==="; cat network/netflow.txt
echo; echo "=== Act 2 - SMB/RDP Windows Security event excerpts ==="; cat network/smb-rdp-events.txt
echo; echo "=== Act 3 - Kerberos event excerpts ==="; cat ad/kerberos-events.txt
echo; echo "=== Act 3 - Service account / SPN audit export ==="; cat ad/spn-listing.txt
} > tailgate-full.txt
for f in guestlist/*.json; do echo "--- $(basename "$f") ---"; cat "$f"; echo; done > guestlist-full.txt
# 4. Copy both into Casky Box's evidence bind mount (live mount, no restart needed).
cp tailgate-full.txt guestlist-full.txt ../casky-box/evidence/
docker exec casky-runner ls /var/casky/evidence/ # confirm they're already there
# 5. Investigate — Tailgate (reactive).
docker exec -it casky-runner casky harness --auto -i /var/casky/evidence/tailgate-full.txt
# 6. Investigate — GuestList (proactive)
docker exec -it casky-runner casky harness --auto -i /var/casky/evidence/guestlist-full.txt
Against the real Tailgate evidence, the classifier independently found and validated 11 MITRE techniques at 87.0% confidence from the combined phishing/network/AD text alone — no hints, no pre-picked skill list:
| # | Technique | Skill | Category |
|---|---|---|---|
| 1 | Phishing: Spearphishing Attachment (T1566.001) | analyzing-email-headers-for-phishing-investigation | forensics |
| 2 | Phishing: Spearphishing Attachment (T1566.001) | analyzing-macro-malware-in-office-documents | malware |
| 3 | User Execution: Malicious File (T1204.002) | analyzing-lnk-file-and-jump-list-artifacts | forensics |
| 4 | Command and Scripting Interpreter: PowerShell (T1059.001) | analyzing-powershell-script-block-logging | incident-response |
| 5 | Command and Scripting Interpreter: PowerShell (T1059.001) | detecting-suspicious-powershell-execution | threat-hunting |
| 6 | Ingress Tool Transfer (T1105) | analyzing-indicators-of-compromise | threat-intel |
| 7 | Valid Accounts: Default Accounts (T1078.001) | analyzing-security-logs-with-splunk | incident-response |
| 8 | Valid Accounts: Default Accounts (T1078.001) | analyzing-windows-event-logs-in-splunk | incident-response |
| 9 | Remote Services: RDP (T1021.001) | detecting-rdp-brute-force-attacks | threat-hunting |
| 10 | Remote Services: SMB/Windows Admin Shares (T1021.002) | moving-laterally-with-netexec | exploitation |
| 11 | Remote Services: SMB/Windows Admin Shares (T1021.002) | analyzing-windows-event-logs-in-splunk | incident-response |
| 12 | Steal or Forge Kerberos Tickets: AS-REP Roasting (T1558.004) | deploying-active-directory-honeytokens | recon |
| 13 | Steal or Forge Kerberos Tickets: Kerberoasting (T1558.003) | analyzing-windows-event-logs-in-splunk | incident-response |
| 14 | Account Discovery: Domain Account (T1087.002) | conducting-internal-reconnaissance-with-bloodhound-ce | exploitation |
| 15 | Phishing: Spearphishing Attachment (T1566.001) | building-incident-timeline-with-timesketch | incident-response |
| 16 | Ingress Tool Transfer (T1105) | collecting-indicators-of-compromise | incident-response |
| 17 | Valid Accounts: Default Accounts (T1078.001) | containing-active-breach | incident-response |
Row 12 is the built-in "catch the agent" check this scenario is built around: the
classifier validated AS-REP Roasting purely from svc-legacyapp's exposed
preauth-disabled flag — even though the Kerberos event log shows no matching request was
ever made. Validated ≠ confirmed exploited.
GuestList's evidence produced an even richer result — 15 MITRE techniques at 70.5% confidence, 22 selected skills, correctly picking up Lateral Tool Transfer and both phishing sub-techniques purely from the correlation notes embedded in the audit JSON.
--auto runs every step's agent for real and produces a real, inspectable
tool-call transcript per step ([VERIFIED] Skill script executed: YES/NO). Open
casky-ui (http://localhost:8766) afterward for the Plan / Execution / Findings /
Remediation tabs.
See the comparison table on the home page for what's different between Section 1 and Section 2.
Done for the day, or resetting for the next attendee? See Cleanup on the Troubleshooting page.