seekrit
Docs/Honey tokens

Honey tokens

A honey token is a decoy credential. It looks exactly like a real seekrit service token, it grants nothing at all, and the moment anyone tries to authenticate with it, seekrit emails your admins and writes the attempt to your audit log.

The point is what it tells you. Every other alert in a secrets manager answers "was this allowed?" — a question with a boring answer most of the time. A honey token answers a different one: is someone reading things they shouldn't be? Nothing legitimate ever holds one, so there is no benign explanation for a trip and nothing to triage. One alert, one conclusion: whatever you planted it in has been read by someone who wasn't supposed to.

note

Honey tokens are a plan feature. Your plan & billing page shows whether your plan includes them; organizations on a plan without it see an upgrade prompt in place of the honey-token page.

Where to plant one

Think about the places a credential ends up that nobody ever cleans out. Those are the places worth watching:

  • An archived or public repository — in .env.example, a stale docker-compose.yml, a commented-out line in CI config.
  • A CI/CD variable on a pipeline you've since retired.
  • A wiki page, runbook, or onboarding doc that lists "the credentials you'll need".
  • A shared password manager entry or team drive folder.
  • A .env.bak or .env.old on a build box or a developer image.
  • A support ticket or chat thread where someone once pasted a secret.

The rule of thumb: plant it where a thief would rummage, and never anywhere your own tooling reads. A honey token has no idea who is holding it — a deploy script that picks one up by mistake trips the alarm exactly as loudly as an intruder would.

note

A honey token is safe to leave lying around. It carries no key material that unlocks anything, holds no grants, and is not a member of any environment, so the worst an attacker can do with one is tell you they found it.

Plant a decoy

caution

The decoy is shown once, when you create it. seekrit stores only a hash of it — the same way it handles real service tokens — so the value can't be recovered later, and not even seekrit's own database reveals what you planted where. Lost it? Delete the decoy and plant a fresh one.

From the dashboard

Open Honey tokens in the sidebar and choose Plant decoy. Give it a name and, optionally, a note recording where you're putting it. The note is repeated back to you in the alert email, which is the whole reason to bother with it: an alert that says "legacy-ci-bait — archived acme/legacy-api repo" tells you what was breached without any digging.

From the CLI

seekrit honey-token create \
  --name legacy-ci-bait \
  --placement "archived acme/legacy-api repo, .env.example"

The decoy goes to stdout and everything else to stderr, so you can pipe it straight where it needs to go:

seekrit honey-token create --name ci-bait --placement "retired deploy pipeline" \
  > /tmp/bait.txt

List what you have planted, and whether anything has taken the bait:

seekrit honey-token list
name             status       planted in                        last tripped          id
legacy-ci-bait   TRIPPED 1×   archived acme/legacy-api repo     2026-08-17T23:57:00Z  skt_BNTz…
wiki-bait        untouched    ops wiki "credentials" page       never                 skt_9dPq…

What happens when one is tripped

The instant a decoy is presented as a credential — on any endpoint, not just secret resolution — seekrit:

  1. Rejects the request. The caller gets exactly the same 401 unknown service token an unregistered token gets, byte for byte. That symmetry is deliberate: an attacker probing credentials must not be able to tell a decoy from a typo, or they'd know to back away quietly.
  2. Writes an audit row (honey_token.tripped) recording the source IP, the user agent, the path they tried, and the decoy's name and placement. It is part of your normal append-only audit trail, so it also flows to your SIEM through audit log export with no extra setup.
  3. Emails your organization's admins, throttled to one message per decoy per hour so a scripted retry loop can't bury the first alert. Every attempt still lands in the audit log — only the email is throttled.

What to do about it

Assume the container leaked, not just the decoy. Someone read the repo, the wiki page, or the CI config you planted it in — so treat every real credential stored alongside it as exposed and rotate it. The decoy itself needs no cleanup: it never granted anything.

The audit log is the record to work from. Filter to honey_token.tripped for the IPs, user agents, and timing of every attempt, including the ones whose emails were throttled.

Honey tokens vs. service tokens

They're deliberately indistinguishable from the outside and completely different underneath:

Service tokenHoney token
Looks likeskt_…skt_… (identical format)
Can decrypt secretsYes, via its key grantsNo — it holds no public key, so nothing can ever be wrapped to it
AuthenticatesYesNever
On useBumps last usedAlerts your admins
Lives inservice_tokensA separate table with no key material

That last row is the load-bearing one. A honey token isn't a service token with permissions switched off — it is a different kind of record entirely, with no public key for a data key to be wrapped to. It unlocks nothing by construction, not by policy, so no future change to the authentication path can accidentally promote a decoy into a working credential.

Deleting a decoy

Deleting one stops it alerting, so pull the bait at the same time — otherwise you have left a credential lying in an archived repo with nothing watching it.

seekrit honey-token delete skt_BNTzs78w3deu06FikXxQNo

Trips already recorded stay in your audit log; that trail is append-only and outlives the decoy.

note

Alerts keep firing for decoys you've already planted even if your organization later moves to a plan without honey tokens. An alarm that goes quiet because a subscription lapsed would be worse than no alarm at all — you'd believe you were being watched when you weren't. You just can't plant or manage new ones until the feature is back on your plan.