Not recorded yet. The lesson below is complete and runnable today — the video is added later without touching this page.
recordings/E2.6.mp4Every other detector needs a threshold, and every threshold is a trade. Deception needs neither — but only if the bait is placed where the agent actually looks, and rotated before it is learned.
Canary tokens in config, environment and artifact metadata (C4.4), and honeypot tasks salted into the benchmark whose cheat path is logged rather than rewarded (C10.3).
Authenticate with a canary and watch a zero-threshold alert fire; then salt a benchmark and read the cheat-attempt rate as a leading indicator.
Every detector in this chapter needs a threshold, and every threshold is a trade. A canary needs neither: nothing legitimate has any reason to touch it, so its false-positive rate is zero by construction rather than by tuning.
What it covers. Authenticate with a canary and watch a zero-threshold alert fire; then salt a benchmark and read the cheat-attempt rate as a leading indicator.
Why a security engineer needs it. Every other detector needs a threshold, and every threshold is a trade. Deception needs neither — but only if the bait is placed where the agent actually looks, and rotated before it is learned. The control it builds is: canary tokens in config, environment and artifact metadata (C4.4), and honeypot tasks salted into the benchmark whose cheat path is logged rather than rewarded (C10.3).
This is a control lesson: it builds the mechanism, then breaks it, so you can see what the control is actually load-bearing for rather than taking the claim on trust.
Every other detector needs a threshold, and every threshold trades misses against false alarms.
Place canaries and honeypot tasks where nothing legitimate has a reason to go.
A false-positive rate of zero by construction — and the number of canaries legitimate work reaches, which destroys that property.
Measure this
| what to measure | denominator or target |
|---|---|
| false-positive rate of the deception layer | zero by construction |
| canaries legitimate work reaches | count; each destroys that property |
tuned detector deception
threshold ---> TP and FP canary ---> any touch is a hit
needs triage needs none: nothing legitimate
finds more has a reason to touch it
finds less, at precision 1.00
canary token in env/config/docs honeypot task with an instrumented
real prefix, real length shortcut that logs and scores 0
both decay: bait that is not rotated is bait that has been learnedEvery detector in this chapter has needed a threshold, and every threshold is a trade between missing things and crying wolf. Deception is the exception: a canary has a false-positive rate of zero by construction, because nothing legitimate ever touches it.
Two controls from the incident register live here, and both are about the environment your harness builds rather than the code it analyses.
Credential canaries (C4.4). Tokens that look genuine — same prefix, same format, same length — placed where an agent or an attacker would plausibly look: config files, environment listings, documentation, artifact metadata. The issuing service alerts on any authentication attempt. There is no legitimate use, so a hit is a confirmed compromise and opens an incident automatically. In the source incident, live credentials found on the public internet were redistributed to the swarm within minutes; a canary alongside them would have carried source IP, user agent and timestamp.
Honeypot tasks (C10.3). Benchmark tasks salted with a plausible-looking shortcut that is instrumented rather than functional, plus tasks whose scoring appears manipulable but where manipulation is detected rather than rewarded. The cheat-attempt rate on those tasks is a leading indicator for the whole fleet — available continuously, not after the fact.
Both share one operational requirement: rotate them. Bait that stays put is bait that gets learned, and a learned canary is worse than none because it tells you the environment is clean when it is only well-mapped.
Anchor → E1.0. The only detector whose interval is the moment of touch. Every other one in the chapter trades detect time against false positives through a threshold; a canary has no threshold to trade, because nothing legitimate has any reason to touch it.
A canary credential is one that nothing legitimate ever uses. That is what makes it valuable: an alert from it has no innocent explanation — there is no false positive to rule out.
The skill does four things:
The skill — skills/detection/canary-and-honeypot-design/SKILL.md
name: canary-and-honeypot-design
description: >-
Place credential canaries and honeypot tasks in an agent's environment so that
an alert has no structurally possible false positive, and measure how fast the
signal decays as agents learn. Use when deception is being added, or when a
detection needs to be one nobody has to triage.
allowed-tools: Read, Grep, GlobA canary credential that nothing legitimate uses produces an alert that needs no triage: the only way it authenticates is that somebody read it and tried it. That property is structural, not statistical, and it is why deception belongs in an agent environment where every other signal is ambiguous.
Designing detection for agent environments, and whenever an existing detection's false-positive rate is the reason it is ignored.
1 — Place canaries where only reading them is unusual. Environment variables, config files, the fixtures a code agent walks. They must be indistinguishable from real ones — a canary named canary_key is a filter, not a trap.
2 — Ensure nothing legitimate uses them. This is the whole property. Check the code, the tests and the deployment. One legitimate reference and the alert becomes triage.
3 — Instrument the authentication path to capture source address and user agent on use. A canary alert with no context tells you that it happened and nothing about who.
4 — Add honeypot tasks for behaviour rather than credentials. A task with an available shortcut that nothing legitimate would take. Log the attempt and score it; this measures inclination, which no credential can.
5 — Measure decay. Agents and operators learn. Model the hit rate over days since placement, with and without rotation, and set the rotation interval from the curve rather than from a calendar.
Input — the fixture committed at the top of scripts/canary_and_honeypot_design.py. Edit it and re-run: the buckets, counts and verdicts below are derived from it, not hard-coded.
Output — the opening lines of a real run:
token source agent verdict
hf_liveTokenNotShown 10.2.0.11 ci-runner normal use
hf_CANARY7Fq2mXvLpR8s 203.0.113.9 python-requests/2.31 CONFIRMED COMPROMISE
ghp_alsoLive 10.2.0.11 ci-runner normal use
sk-CANARYd3Vn8yHc2Uae 203.0.113.9 python-requests/2.31 CONFIRMED COMPROMISE
canary hits: 2 false positives possible: 0
Not zero because the detector is good - zero because nothing legitimate
The run continues past this. test_skills.py executes the script on every build, with no model configured — so what CI proves is that it runs and refuses legibly, not that it prints these lines. The output above is a recorded run against a real model, and nothing re-diffs it: a model's answer is not reproducible, and this repository does not claim otherwise anywhere it can be checked.
{
"canaries": [{"id": "str", "placed_in": "str", "indistinguishable": true, "legitimate_refs": 0}],
"alerts": [{"canary": "str", "source_ip": "str", "user_agent": "str", "false_positive_possible": false}],
"honeypot_tasks": [{"task": "str", "shortcut": "str", "attempts": 0}],
"decay": {"days": [0], "hit_rate": [0.0], "rotation_days": 0}
}
Three ways to do this lesson. Pick one. They run the same procedure against the same code — what changes is who drives it, and how much you see.
The agent reads the lesson, explains the idea, fetches the code, runs the check and answers your questions as you go. This is the one to take if you are here to learn.
Install it, once. From the folder you cloned. --all does every agent it finds on your machine:
python3 scripts/install_skills.py --all --lessons E2.6Then restart your agent and open it in that folder. On Windows, if python3 says Python was not found, use python instead.
Then pick e2-6-honeypots:
| agent | install just for this agent | start it |
|---|---|---|
| Claude Code | python3 scripts/install_skills.py --tool claude --lessons E2.6 | type /e2-6-honeypots |
| GitHub Copilot (VS Code) | python3 scripts/install_skills.py --tool copilot --lessons E2.6 | type /e2-6-honeypots in Chat |
| Cursor | python3 scripts/install_skills.py --tool cursor --lessons E2.6 | type / in Agent chat and search for it |
| Codex | python3 scripts/install_skills.py --tool agents --lessons E2.6 | type $e2-6-honeypots, or run /skills |
No agent, no conversation. The same lesson executes and prints the same readback. Take this one if you have no assistant, if you are reviewing rather than learning, or if you want the result without the teaching around it.
python3 scripts/lesson.py E2.6Neither of the above, and no model needed. The first command writes CyberTravels exactly as it stood at the end of this lesson; the second prints the diff — the lines this lesson added or changed, and nothing from any later one.
python3 scripts/checkpoint.py --at E2.6 --out work/cybertravels
python3 scripts/checkpoint.py --at E2.6 --diffOn Windows, type python wherever these say python3 — and use \ instead of / in the paths. Everything else is identical. A0.0 step 2 explains why.
Ways 1 and 2 need a model; way 3 does not. A signed-in Claude Code CLI needs no API key, and any OpenAI-compatible endpoint works too. With neither, the audit exits 2 and says so rather than inventing an answer. A0.0 sets this up.
Ways 1 and 2 both end with the same readback: What I did, What changed, The number and Read this next. A step that was skipped or refused is reported as exactly that, never as a pass.
If you did the last lesson’s challenge, expect this to stop. Most challenges ask you to edit the code, and ways 1 and 2 will not overwrite your edits: you get stopped, not a failure, with two options — --out for a fresh folder that keeps your work, or --force to discard it and start this lesson clean.
Two canary authentications out of four events are confirmed compromises with source IP and user agent attached, and no false positive is structurally possible. Both honeypot tasks log a cheat attempt and score zero for it. An unrotated canary's detection rate falls to 0% once learned — reporting a clean environment that is only well-mapped — while rotation holds it at 100%. Deception finds fewer things than the volume detectors and finds them at precision 1.00.
Place one canary credential in the environment your agents run in, wired to a real alert, and leave it. The interesting outcome is not the alert; it is discovering, six weeks later, which systems can even see it.
What you can do now. You can shorten detect: a lake tiered by the queries that read it rather than by whoever holds the invoice, detections for both subjects — the agent and the platform running it — each carrying a MITRE technique, rules scored against traffic that is not the incident, and the one detector that needs no threshold at all.
What you still cannot do. A detection fires. It does not investigate. Understanding still costs an analyst's reading speed, and the obvious fix — hand an agent broad read across the estate — is frequently what the incident was.
Chapter E3 shortens understand, and spends part of it deliberately: admission rules before anything runs, scope along the delegation graph, then intel and the hunt for what no rule covers.
Tools used
Skill source: skills/detection/canary-and-honeypot-design