A canary token is a piece of bait, such as a fake AWS access key, a document or a URL, that sends you an alert the moment someone uses it. A honeytoken is the same idea applied to credentials and data: a key, secret or record that no legitimate person or system should ever touch. In AWS, the classic honeytoken is an access key for an IAM user with no permissions. You leave it where an attacker would look, and AWS CloudTrail, the service that records API calls in your account, logs any attempt to use it.
Because nobody has a reason to use the key, any use is worth acting on. That is why decoy credentials produce close to zero false positives, and why they often catch an intruder during reconnaissance, minutes after a leak, instead of weeks later. This guide covers how the AWS pattern works, what CloudTrail records for a denied call, where to plant decoys and the mistakes that make them fail.
Canary Tokens vs Honeytokens: What the Terms Mean
- Canary token: named after the canaries miners carried as an early warning. Thinkst made the term popular with canarytokens.org, a free service that generates more than 30 token types, including AWS API keys, Word documents, kubeconfig files and DNS names. Thinkst calls them "motion sensors for your networks, computers and clouds."
- Honeytoken: any fake credential or data record planted to detect misuse. MITRE D3FEND, a public catalog of defensive techniques, lists it as Decoy User Credential (D3-DUC): "a credential created for the purpose of deceiving an adversary."
- Honeypot: a whole decoy system, such as a fake server or login page, that attracts an attacker and records what they do. A honeytoken is a decoy item. A honeypot is a decoy place. Our guide to AWS honeypots and deception as code covers the larger setups.
In practice people use "canary token" and "honeytoken" interchangeably. Both are tripwires.
Why Decoy Credentials Have Near Zero False Positives
Most detection rules look for unusual behavior inside real activity, so they misfire whenever a real person does something unusual. A decoy flips that around. The access key belongs to no workload, no pipeline and no engineer. If CloudTrail shows it in a request, someone found it and tried it. The main routine false alarm comes from your own tooling, for example a secret scanner that validates the keys it finds, so document and allowlist your own tests.
Attackers also test stolen keys quickly. MITRE ATT&CK, the public catalog of attacker techniques, lists searching files for stored credentials as technique T1552.001 and notes that cloud credentials often sit in local configuration files. A common first move after finding a key is aws sts get-caller-identity, which asks AWS which identity the key belongs to. AWS documents that this call needs no permissions, so it succeeds even for a key with none, and CloudTrail records all STS calls.
How the AWS Honeytoken Pattern Works
- Create the decoy identity. Make an IAM user with a believable name, such as
svc-backup-ci, attach no policies, and create one access key. An access key is the pair of an access key ID (starting with AKIA) and a secret access key that tools like the AWS CLI use to sign requests.
- Record every Region. Confirm a multi-Region CloudTrail trail is logging management events. A trail keeps events beyond the 90-day Event history and forwards them to S3, CloudWatch Logs and Amazon EventBridge. Management events are control-plane calls such as ListBuckets or GetCallerIdentity.
- Alert on the key. Match any event whose
userIdentity.accessKeyIdequals the decoy key ID.
- Plant it and test it. Put the key somewhere tempting, then use it once yourself to confirm the alert arrives.
When the decoy key calls an API it has no permission for, the call fails, but CloudTrail still records it with the caller identity, source IP, user agent and an errorCode. AWS Security Hub's CIS control for unauthorized API calls filters on error codes matching AccessDenied* or *UnauthorizedOperation, the form EC2 uses. A trimmed excerpt of a trip looks like this (values are examples):
{
"eventSource": "s3.amazonaws.com",
"eventName": "ListBuckets",
"awsRegion": "us-east-1",
"sourceIPAddress": "203.0.113.24",
"userAgent": "aws-cli/2.15.33 Python/3.11.8 Linux/6.5.0",
"userIdentity": {
"type": "IAMUser",
"userName": "svc-backup-ci",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE"
},
"errorCode": "AccessDenied",
"readOnly": true,
"eventCategory": "Management"
}
An EventBridge rule on the default event bus can match the key directly:
{
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"userIdentity": {
"accessKeyId": ["AKIAIOSFODNN7EXAMPLE"]
}
}
}
Two details catch people out. First, GetCallerIdentity and ListBuckets are read-only management events, and a rule in the normal ENABLED state never matches them. Set the rule state to ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS, which AWS supports through the CLI and CloudFormation. Second, CloudTrail records each call in the Region it was sent to, and requests to the STS global endpoint land in US East (N. Virginia). Deploy the rule in every Region you use, or send the multi-Region trail to CloudWatch Logs and alert with a metric filter such as { $.userIdentity.accessKeyId = "AKIAIOSFODNN7EXAMPLE" }.
Decoy S3 Buckets and Secrets Manager Secrets
Keys are only one kind of bait. Two other decoys work well in AWS.
- Decoy S3 bucket: name it after something worth stealing, such as
acme-db-exports-2024, and put a few plausible files in it. Bucket-level calls such as ListBuckets and GetBucketAcl are management events, but object reads such as GetObject are data events, which CloudTrail does not log by default. Turn on S3 data events for the decoy bucket alone, using an advanced event selector on its ARN, so the extra volume stays small.
- Decoy secret: create a Secrets Manager secret named like
prod/payments/db-adminwith a fake value. CloudTrail records every Secrets Manager API call, so a GetSecretValue on the decoy appears in your trail. It is read-only, so the same EventBridge rule state applies.
- Pair them: leave a config file in the bucket that points at the secret. An attacker who follows the trail trips two wires, and you see the path they took.
| Decoy | Looks like | What records the touch | Setup note |
|---|---|---|---|
| IAM access key, no permissions | Credentials file, CI variable | CloudTrail management events, including denied calls | Rule state must include read-only events |
| S3 bucket | Backup or export bucket | Management events for bucket calls, data events for object reads | Enable data events on the decoy bucket |
| Secrets Manager secret | Production database password | CloudTrail management events such as GetSecretValue | Read-only, same rule state |
| canarytokens.org AWS key | A key from a free service | Thinkst's own logging pipeline | No AWS setup, alerts in 2 to 30 minutes |
Where to Plant Canary Tokens
Plant decoys where an intruder, or an insider with too much curiosity, would look first:
- CI/CD variables: a variable like
AWS_ACCESS_KEY_ID_LEGACYin an old pipeline project. Attackers who compromise a build runner often dump its environment variables.
- Wikis and runbooks: a page titled "break-glass access" that includes a decoy key.
- Laptops: a
[backup-admin]profile in~/.aws/credentials, the default file the AWS CLI reads.
- Old repositories: a decoy key committed to an archived internal repo. Keep these in private or internal repos, where a trip means someone got inside.
- Images and backups: container images, Terraform state backups and shared drives.
Use one token per location, and keep a list of where each one lives. When a token fires, that list tells you which place leaked.
Common Mistakes With Canary Tokens
- Expecting instant alerts. CloudTrail typically delivers logs within an average of about 5 minutes of an API call, and AWS does not guarantee that time. Thinkst warns its AWS key alerts can take between 2 and 30 minutes. Plan your response in minutes, and route the alert to someone who will see it.
- Tokens that look fake. A user named
honeytoken-test, a file calledcanary.txtor an empty bucket created yesterday gives the game away. Match your real naming. Careful attackers can also check which account a key belongs to: STS GetAccessKeyInfo returns the account ID for any access key ID, so keys issued from a shared third-party account are easier to spot than keys from your own.
- Missing read-only events or Regions. The default EventBridge rule state and a single-Region rule both leave gaps, as covered above.
- Forgetting to rotate. A tripped token is burned, so replace it. Refresh decoys when people who know about them leave, and delete orphaned decoys so they do not confuse audits. Never add permissions to make a decoy look realistic.
- Never testing. Trip each token after you plant it, and again after any change to trails or alert routing.
How ops0 Deploys Honeytokens and Honeypots in AWS
ops0 turns this setup into a few clicks. Pick the target AWS account and Region, a naming theme that makes decoys look tempting, Terraform or OpenTofu, and the severity a trip should carry (P1 or P2). ops0 ships the decoys as a blueprint:
- An inactive honeytoken credential that fires on any use (on by default)
- A decoy storage bucket with a paired decoy secret (on by default)
- An optional decoy database endpoint
- An interactive SSH honeypot that records every command typed
- A fake admin panel that captures attempted logins
A trip opens an incident in ops0 and fires your existing alert rules. Each incident carries attacker context: geolocated IP, ISP and network, proxy, VPN, hosting or Tor flags, an IP threat score, the user agent, usernames and passwords tried and commands typed. A Fake test sends a synthetic trip through the pipeline. A Real test gives you instructions to touch the decoy yourself, so you can prove detection works end to end. Teardown removes every decoy and its detection.
From Trip to Fix: Detect, Remediate, Prevent
A decoy alert pays off when it changes what gets built. When an attacker probes a decoy, ops0 ranks candidate changes in your real projects that reduce the same exposure, with the resource, the change, effort, risk reduction and rationale. Draft policy writes a guardrail that blocks the probed pattern, such as public storage, permissive IAM, open ingress or unencrypted secrets, and you apply it to the projects you choose. Platform engineers see the fix in the projects they already own.
If someone later asks ops0 in chat for a change close to an attacked surface, such as a public bucket in the same account, ops0 pauses and asks for explicit confirmation, showing the decoy, the attacker's origin and when it was last seen. Decoy activity also feeds an evidence report through a compliance lens such as SOC 2, ISO 27001 or PCI DSS. See ops0 security and compliance in ops0.
Setup, decoy types and alert routing are covered in the honeypots docs.
What is a canary token?
A canary token is a piece of bait, such as a fake AWS access key, document, URL or DNS name, that sends an alert when someone opens or uses it. Thinkst offers a free generator at canarytokens.org with more than 30 token types. Because no legitimate user should touch the token, an alert is a strong sign that someone found something they should not have.
What is the difference between a honeytoken and a honeypot?
A honeytoken is a decoy item, such as a credential, secret or database record. A honeypot is a decoy system, such as a fake server or admin login page, that attracts an attacker and records their activity. Many deception programs use both: honeytokens to detect a leak early and honeypots to learn what the attacker does next.
Does CloudTrail log access denied API calls?
Yes. When a request fails authorization, CloudTrail records the event with the caller identity, source IP, user agent and an errorCode such as AccessDenied, or one ending in UnauthorizedOperation for EC2. That is why an access key with no permissions still works as a honeytoken. S3 object reads are data events, so they only appear if you enable data events for that bucket.
How fast does a canary token alert arrive in AWS?
Usually within minutes. AWS says CloudTrail typically delivers logs within an average of about 5 minutes of an API call, without a guarantee, and Thinkst says its AWS key alerts can take between 2 and 30 minutes. Plan your response around that delay.
Where should I put honeytokens?
Put them where attackers search for credentials: CI/CD variables, wiki runbooks, the ~/.aws/credentials file on laptops, archived internal repositories, container images and backups. Use one token per location and keep a record of where each one lives, so a trip tells you exactly which place leaked.
- How CloudTrail works: Amazon Web Services. Event history retention and typical log delivery time.
- Receiving read-only management events from AWS services: Amazon Web Services. The ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS rule state.
- Security Hub CSPM controls for Amazon CloudWatch: Amazon Web Services. CloudWatch.2 filter pattern for unauthorized API calls.
- GetCallerIdentity: Amazon Web Services. No permissions are required to call it.
- AWS API Keys Canarytoken: Thinkst Canarytokens. How the free AWS key token works and its alert delay.
- Decoy User Credential (D3-DUC): MITRE D3FEND. Definition of a decoy credential.