# 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](/docs/guides/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

> **Warning:** 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

```sh
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:

```sh
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:

```sh
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](/docs/guides/audit-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 token             | Honey token                  |
| ---------------------- | ------------------------- | ---------------------------- |
| Looks like             | `skt_…`                   | `skt_…` (identical format)    |
| Can decrypt secrets    | Yes, via its key grants   | No — it holds no public key, so nothing can ever be wrapped to it |
| Authenticates          | Yes                       | Never                        |
| On use                 | Bumps `last used`         | Alerts your admins           |
| Lives in               | `service_tokens`          | A 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.

```sh
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.

## Related

- [Service tokens](/docs/guides/service-tokens) — the real machine credentials
  honey tokens imitate.
- [Email notifications](/docs/guides/notifications) — the **Honey token tripped**
  toggle, and every other alert seekrit sends.
- [Audit log export](/docs/guides/audit-export) — get trips into your SIEM.
