Incident
A.env.bak carrying production-grade secrets was committed to github.com/bucks-pay/facilitator
(present in commits 25bd513 and 4e8c83b). It was later removed from tracking with
git rm --cached .env.bak and .env.bak is now in .gitignore. Removal from HEAD is NOT
remediation: the values remain in git history and in every existing clone/fork, in any CI log
that printed them, and with every current/former collaborator who pulled. Anyone with repo
history has every value below. The blast radius is the full set of secrets listed in
the Burned secrets section below. The only fix is to rotate each to brand-new material and abandon the old.
Burned secrets (rotate ALL)
Exact keys present in the leaked.env.bak (verified from the file; values intentionally not
reproduced here).
Non-secret values also present (no rotation needed):
PORT, SWAP_DEFAULT_SLIPPAGE_BPS,
SWAP_MAX_SLIPPAGE_BPS, SWAP_QUOTE_TTL_SECONDS.
The mainnet sponsor
STELLAR_SPONSOR_SECRET_PUBNET was NOT in .env.bak, but it MUST be
generated fresh on a clean host post-incident and MUST differ from the leaked address above -
enforced by scripts/check-no-committed-env.sh Guard 2.Rotation procedure
Apply these four steps to every row above:- Generate new material on a clean host. Never paste an old value into a new file; never reuse a leaked key on a “fresh” account.
- Deploy to the secret manager / deploy target - the facilitator’s
SecretProvider:KmsSecretProviderin prod, a gitignored.envin dev. Never into a tracked file. - Revoke / abandon the old value at its source: gateway revoke for API keys (0x/1inch/
API_KEY); for on-chain keys, sweep all funds out and never reuse the address. - Verify the new value works and the old value fails: old
API_KEY->401; leaked sponsor G -> zero balance and no longer referenced anywhere.
GDKACWHU...4RPI to the new sponsor (or treasury), submit it once,
then record the leaked G as abandoned in this doc. Never re-fund it.
Never commit a secret file again (controls)
.gitignorein both repos ignores.envand.env.*and explicitly.env.bak/.env.local, allowing ONLY.env.example. (SDK:.env,.env.*,!.env.example; facilitator:.env,.env.bak,.env.local,.env.*.local.)scripts/check-no-committed-env.shruns in CI and the release gate - fails if any.env*(≠.env.example) is tracked, and fails if the configured pubnet sponsor equals the leaked address.- Pre-commit / CI secret scanner (
gitleaksortrufflehog) blocks secret-shaped strings before they land. This extendsscripts/check-no-secrets-in-src.sh(blocksS...seeds / PEM markers /apiKeyliterals inpackages/*/src) to tracked files anywhere, not justsrc.
Post-rotation verification
- Leaked sponsor
GDKACWHU...4RPIbalance == 0 (drained + abandoned). - New sponsor funded and referenced via the secret manager (never a tracked file).
- Old
API_KEYreturns401at the gateway; new key distributed to the BFF. -
bash scripts/check-no-committed-env.shexits 0. - No
.env*(except.env.example) tracked in either repo:git ls-files | grep -E '(^|/)\.env'shows only*.env.example. - 0x / 1inch / Calibur / EVM relayer + deployer keys rotated and old ones revoked/emptied.

