Canaries
List, add, rotate and remove canary tokens - and what happens to them when the daemon restarts.
| Method | Path | Auth |
|---|---|---|
| GET | /api/canaries | Dashboard token |
| POST | /api/canaries | x-grith-csrf |
| POST | /api/canaries/{id}/rotate | x-grith-csrf |
| DELETE | /api/canaries/{id} | x-grith-csrf |
⚠️This registry is in memory
Anything added through these routes lives in the running daemon and is gone when it stops. The
only durable registration is [[canary.tokens]] in config/filters/canary.toml, picked up at
daemon start. See Canary tokens.
The canary shape
Three fields, and the token value is not one of them:
{ "id": "5f2c9e1a-...", "label": "aws-prod-decoy", "value_prefix": "9a3f..." }value_prefix is the first four characters of the value with an ellipsis after them, and
nothing more. Returning the value would defeat the trap - a compromised dashboard read would
hand an agent the exact string it must not exfiltrate.
GET /api/canaries wraps them as {items, total}.
POST /api/canaries
label is required and must not be empty. Then either supply value or set
generate: true, but not both:
{ "label": "aws-prod-decoy", "generate": true }A generated value is 48 hex characters. Success is 201 Created with the canary shape. An
empty label is 400 INVALID_LABEL; supplying neither value nor generate, both at once,
or an empty value, is 400 INVALID_VALUE.
POST /api/canaries/{id}/rotate
Same body minus the label: value or generate: true. The id keeps its label and gets a
new value, so anything that already leaked stops matching. Returns the canary shape, or
404 NOT_FOUND.
DELETE /api/canaries/{id}
{"status": "removed", "id": "..."}, or 404 NOT_FOUND.
What grith does not do
It never plants the token anywhere. Writing the decoy into a plausible file - a stale
credentials backup, an unused .env - is entirely on you. grith only recognises the string
when a call tries to carry it out, and scores that at 9.5, well above the deny line.