8 min read · github · stripe · npm · dns · deployment
How supply chain honeytokens work (GitHub, Stripe, npm, PyPI, Docker)
These tokens look like real vendor credentials but detect via DNS when the planted hostname is resolved. Here is the mechanism, the best placement tactics, and how to test.
What are supply chain honeytokens
HorasEye supply-chain honeytokens cover GitHub PATs, Stripe live keys, npm tokens, PyPI tokens, and Docker registry credentials. Each one gives you a format-accurate decoy (sk_live_ for Stripe, ghp_ or github_pat_ for GitHub, npm_ for npm, and so on) paired with a set of companion hostnames that act as DNS tripwires. When something resolves one of those hostnames, you get an alert.
Why the credential looks real
Attackers and automated scanners decide what to steal based on format. A string that starts with sk_live_ gets flagged as Stripe. A string that starts with ghp_ gets flagged as a GitHub classic PAT. HorasEye generates these with the correct prefix, correct length, and correct character set. To a scanner, a grepper, or a human reading a leaked .env, the credential looks exactly like the real thing.
Where the tripwire actually is
The credential itself is inert. The sensor is the companion hostname. When you create a supply-chain token, HorasEye gives you a unique callback hostname and a downloadable .env bundle. That bundle places the decoy key next to variable names like GITHUB_API_URL, BILLING_API_URL, PAYMENTS_CALLBACK_HOST, npm_config_registry, INTERNAL_GIT_HOST, PACKAGE_REGISTRY_URL, and similar. These look like internal service endpoints or private registries. When any tool, script, or person resolves one of those hostnames, HorasEye authoritative DNS captures the lookup and fires an alert.
Why the real vendor never alerts you
HorasEye does not control Stripe, GitHub, or npm. If someone pastes your decoy sk_live_ into a curl against api.stripe.com, Stripe will reject it (invalid key), but HorasEye will not see that request. The detection path is intentionally DNS on the companion hostname. That is why the .env bundle is the recommended download: it plants both the bait key and the sensor hostname together.
GitHub PAT: where to plant it
The .env bundle includes GITHUB_TOKEN with the PAT, GITHUB_API_URL pointed at your callback, an npm_config_registry, and several internal hostnames. Plant this where CI secrets leak: .env files committed to private repos, backup S3 buckets, ticketing attachments, Confluence or wiki pages, onboarding docs, or shared drives. Attackers who find a GitHub PAT often also try to use any registry URL or API base URL sitting next to it, especially if it looks like an internal npm mirror or a Git credential helper endpoint. That resolution is the trigger.
GitHub PAT: how to test
On the token page, click Send test probe or run the dig command. Then check Trigger History. For a realistic path, download the .env bundle, place it where your tooling would read it, and run a command that references GITHUB_API_URL. For example: curl -sI https://YOUR-CALLBACK-HOST/api/v3 (that resolves the hostname and fires). A git clone using ghp_...@github.com/... against the real github.com domain does not trip the wire because it does not resolve your callback hostname. The .env bundle format is designed for the common case where stolen .env files get sourced by tooling that reads all the configured URLs, not just the token line.
Stripe key: where to plant it
The .env bundle includes STRIPE_SECRET_KEY (sk_live_...), STRIPE_API_KEY (same value), a STRIPE_WEBHOOK_SECRET (whsec_...), and companion variables like BILLING_API_URL and PAYMENTS_CALLBACK_HOST. Plant this in the same places a production .env backup would leak: S3 config buckets, deploy pipeline secret dumps, internal wikis, developer laptops, staging .env files left on servers, or Docker image layers. If you also plant BILLING_API_URL or PAYMENTS_CALLBACK_HOST in an application config, any startup or health check that resolves that hostname is a trigger.
Stripe key: how to test
Same as GitHub: Send test probe or dig from the token page, then check Trigger History. For a realistic path, download the .env bundle, source it, and run something that resolves the callback host. For example: curl -sI https://YOUR-CALLBACK-HOST/v1/charges (resolves, fires an alert, and gets a connection error because nothing serves the Stripe API there). If you instead post the sk_live_ to api.stripe.com, Stripe rejects it as invalid and HorasEye stays silent. That is expected.
npm, PyPI, and Docker: same pattern
The .env bundle includes the decoy token (npm_, pypi-, dckr_pat_) and companion hostnames styled as registries (npm_config_registry, PIP_INDEX_URL, DOCKER_REGISTRY). Plant in the same leaked-secret locations. Detection fires when the registry URL or any companion hostname is resolved.
Making the bait irresistible
Realistic file naming matters more than the secret itself. Name the .env file after a real project, team, or service: .env.payments-prod, .env.release-pipeline, ci-secrets-backup-2026.env. Place it among real files. On a shared drive, it should sit next to actual project folders. In a backup bucket, it should match the naming convention of other backups. A file called test-decoy.env gets deleted. A file called .env.billing-v2 gets opened.
Layering the .env bundle
Inside the .env bundle, every variable name is chosen to look like a real CI or infrastructure config. INTERNAL_GIT_HOST and PACKAGE_REGISTRY_URL look like private infrastructure. npm_config_registry and GIT_CREDENTIAL_URL look like developer tooling. An attacker who sources the whole file, or a script that processes every URL in it, will resolve at least one callback hostname.
Combine with other token types
A supply-chain .env on its own is strong, but pairing it with a nearby HTTP beacon document or a QR code in the same folder adds a second detection layer. If the attacker reads the file but never resolves the hostname (for example, they only paste the key into a vendor dashboard), the DNS tripwire stays silent. A tracking-pixel HTML file next to the .env catches the "opened the folder and browsed around" path.
What fires and what does not
Any DNS resolution of the callback hostname fires: dig, curl, a browser, or a tool that sources the .env and tries the configured URLs. The .env bundle is built so that common CI runners, package managers, and API clients resolve at least one hostname when they ingest the file. What does not fire: pasting the decoy key into the real vendor portal or API (Stripe Dashboard, GitHub Settings, npmjs.com). The vendor rejects it, but HorasEye never sees that request. The companion hostname must be resolved for detection to happen.
Allowlist your decoy in secret scanners
Tools like truffleHog, GitLeaks, or Snyk will flag the decoy key as a real leaked secret. Add it to your scanner allowlist so your team does not chase a false positive. The token page shows the value for this purpose.