Plan d’action — Offboarding
Objectif : 0 regain d’accès. Couper les comptes, rotater les secrets qu’ils ont déjà clonés en local, vérifier qu’il ne reste rien d’exploitable. Runbook détaillé (phases + tests + scripts) : docs/OFFBOARDING_CHECKLIST.md.
Surface concernée (rappel rapide)
- (pejisdev) — admin
HyperSwap-Labs/charting_library; push surinterface,terminal-perps,api-front-hyperswap,grid-front-hyperswap; commits dansindexer-terminal. - (ExceptHL) — push sur
interface,terminal-perps,api-front-hyperswap,grid-front-hyperswap. - Repos prod & secrets en jeu :
terminal-perps/server/.env,hs-interface-lts,indexer-terminal,shadow-syndicate/*.
Type 1 vs Type 2 — la distinction qui structure tout
- Type 1 — comptes personnels (login propre) : MongoDB Atlas, Railway, Cloudflare, AWS IAM, Privy, Banxa, Sentry, GitHub orgs, SSH Hostkey, Tawk.to, Yandex, GA4. → Phase 1 suffit.
- Type 2 — credentials partagés (valeurs en .env / hardcodés) :
MONGODB_URL,INDEXER_DATABASE_URL,JWT_SECRET,PRIVY_APP_SECRET,BANXA_API_SECRET,AWS_ACCESS_KEY_*,ENCRYPTION_KEY, clé Alchemy leakée, Telegram bot tokens, npm publish tokens. → Seule la Phase 2 (rotation) tue l’accès.
charting_library: PJ est ADMIN. Transférer admin àHyperSwapXAVANT de le retirer (sinon repo orphelin).shadow-syndicate: admin =kindex. Il peut ré-inviter en 30s. Briefer kindex ou faire passer HSX admin avant Phase 1.indexer-terminaldefaults committés (GF_SECURITY_ADMIN_PASSWORD=admin, Postgresindexer_password). Vérifier en Phase 0 que la prod override, sinon les rotations Phase 2 ne servent à rien (bypass via les defaults).
Phase 0 — Préparation (T-2h → T-30min, sans qu'ils le sachent)
- Canal de coordination privé (CTO + DevOps + 1 personne dédiée révocation) ; aligner timing avec RH.
- Pré-générer toutes les nouvelles valeurs de secrets dans 1Password / Vault partagé.
- Préparer les scripts de redéploiement Railway / Cloudflare Pages (avec nouveaux env vars) — ne pas déclencher.
- Snapshot Postgres + MongoDB (anti-sabotage entre T+0 et T+30min).
- Vérifier qu’on a les credentials owner de chaque dashboard (Atlas, Railway, AWS, Cloudflare, Privy, Banxa, LiveKit, Sentry).
- Vérifier que la prod override les defaults
indexer-terminal:ssh root@146.0.73.21 'grep -i security_admin_password /etc/grafana/grafana.ini'.
Phase 1 — Kill sessions (T+0 → T+5min, en parallèle de Phase 2)
- GitHub : retirer des orgs (HSX-Labs, HyperswapFoundation, shadow-syndicate). Pour les outside-collab, boucle
gh api -X DELETE repos/{org}/{repo}/collaborators/{user}. - SSH Hostkey VPS (146.0.73.21) : retirer leur clé publique de
/root/.ssh/authorized_keys; si root password partagé, le changer maintenant. - Cloudflare, AWS Console (IAM disable), MongoDB Atlas (Project Access), Railway (Members), DigitalOcean, Vast.AI, Hostkey provider, Privy (4 apps), Banxa, LiveKit, Sentry, Tawk.to, Yandex Metrika, GA4, Mobula / NewsData / Financiya / Transak.
Checkpoint : ils ne peuvent plus se connecter avec leur propre compte. Mais ils ont encore les secrets locaux → continuer Phase 2.
Phase 2 — Rotation des secrets (T+5 → T+30min)
2a. Backend — terminal-perps/server/.env
MONGODB_URL: changer le password userevan-hldans Atlas → update Railway env → redeploy server.INDEXER_DATABASE_URL:ALTER USER indexer WITH PASSWORD 'newpw';sur Hostkey ;LIQUIDSCAN_DATABASE_URLidem sur 54.37.85.136.JWT_SECRET: nouveau 256-bit hex, redeploy. ⚠ invalide tous les JWT users actifs.PRIVY_APP_SECRET+PRIVY_AUTH_PRIVATE_KEY: rotate dans Privy + update Railway env.BANXA_API_KEY/_SECRET,LIVEKIT_API_KEY/_SECRET,TRANSAK_API_KEY/_SECRET(⚠TRANSAK_*shippé en frontend → redeploy front simultané),AWS_ACCESS_KEY_ID/_SECRET(IAM new key + disable old).MOBULA_API_KEY,FINANCIYA_API_KEY,NEWSDATA_API_KEY: rotate.REFERRAL_CLAIM_PRIVATE_KEY: ⚠ clé de signature on-chain → régénérer puis rotater l’authorized signer dans le contrat (tx on-chain).ANONYMIZE_SALT: rotater (casse les hashes anonymisés existants — accepter la perte d’historique).
2b. Frontend — hs-interface-lts / interface
ENCRYPTION_KEY(XOR hardcodé) : changer la valeur, redeploy front, regénérer tous lesx-client-tokencôté CF Workers.SENTRY_AUTH_TOKEN: Sentry → Auth Tokens → revoke + create + update GitHub Actions secret.
2c. shadow-syndicate (RRC + Grid)
- 🔥 Alchemy key leakée
qZxKitp1_VDz9MuohnrZQ4KUTHtaQ-6g(api-front-hyperswap/.env.development) → DELETE dans Alchemy + nouvelle clé en GitHub Actions secret. Purger l’historique git. - Telegram bot tokens (
@roachracingclub,@mineasudasd_bot) → @BotFather/revoke. api-dev2.roachracingclub.comadmin password (si l’employé l’avait).
2d. Supply chain
- NPM publish tokens
@hyperswap-labs/*→ revoke tous + 1 token org-shared en GitHub Actions secret. - Cloudflare API token (utilisé par
deploy.yml) → revoke + create + update GitHub Actions secret. REFERRAL_API_KEY(Grafana) → noter, ajouter à.env.example, redeploy Grafana.
2e. Defaults committés à override (CRITIQUE)
- Si Phase 0 a montré que la prod utilise les defaults d’
indexer-terminal/docker-compose.yml: overrideGF_SECURITY_ADMIN_PASSWORD+POSTGRES_PASSWORD, restart Docker.
Checkpoint : tous les secrets locaux de sont des chaînes inertes. Les publier sur Twitter ne donne plus accès à rien.
Phase 3 — Cleanup (T+30min → T+24h)
- Boucle
gh api -X DELETEsur tous les repos outside-collab (HSX-Labs :interface,terminal-perps,charting_library,indexer-terminal; shadow-syndicate :api-front-hyperswap,grid-front-hyperswap). - Wallets on-chain : retirer de
MODERATOR_ADDRESSESetWHITELISTED_WALLETS(server/.env) → redeploy. - Slack / Discord / Telegram team channels, Notion / docs internes, Apple Dev / Google Play, 1Password / Bitwarden / Vault partagé.
Phase 4 — Audit & monitoring (T+24h → T+7j)
- GitHub Audit log (chaque org, 7 derniers jours), AWS CloudTrail, Cloudflare audit log, MongoDB Atlas Activity Feed, Privy Activity log.
- Hostkey VPS :
last -F | head -50; lastlog | head+ scan des fichiers récemment modifiés. - Failed-login alerts pendant 7 jours (détection d’une tentative de retour).
Phase 4.5 — Test de non-régression (à T+30min, AVANT de clore)
Prendre le .env qu’ils possédaient et tester chaque ligne. Si un seul test passe, retour Phase 2 sur la ligne précisément.
- MongoDB :
mongosh "$OLD_MONGO" --eval "db.adminCommand('ping')"doit échouer (Authentication failed). - Postgres :
psql "$OLD_PG" -c "SELECT 1"doit échouer. - AWS :
aws sts get-caller-identityavec les anciennes keys doit retourner InvalidClientTokenId. - Privy / Banxa : appel API avec les anciens secrets doit retourner 401/403.
- JWT : forger un JWT avec l’ancien
JWT_SECRETet hit l’API → 401. - Alchemy (clé leakée) :
eth_blockNumberavec l’ancienne clé → 401/403. - SSH Hostkey : tentative connexion avec leur ancienne clé → Permission denied.
Phase 5 — Vérifications finales
- Comptes “admin partagés” (ex:
admin@hyperswap.exchange) dont plusieurs personnes connaissaient le password. - Outils internes auto-hébergés (Grafana, métriques, k8s admin si applicable).
- Cron / scripts sur Hostkey utilisant un de leurs tokens :
crontab -l; ls /etc/cron.*. - Cloudflare Workers publiés sous leur Account ID perso (workers déployés perso peuvent encore tourner).
- Owner du Worker
proxy-nft-mint.hyperswapx.workers.dev.
Spécifique PJ (pejisdev)
- ADMIN charting_library → transfert admin à
HyperSwapXAVANT remove. - Commits dans
indexer-terminal→ connaît la structure DB et les defaults. Override defaults obligatoire avant Phase 2. - Push très récent sur
terminal-perps(jusqu’au 2026-04-22) → audit ses derniers commits pour repérer toute backdoor.
Spécifique Evan (ExceptHL)
- Push (pas admin) sur 4 repos. Pas d’access cross-org étendu détecté → risk medium.
- Email obfusqué (
@users.noreply.github.com) → traçage hors-GitHub impossible. - Activité publique récente sur d’autres orgs (
jovanpanetie/stake-engine-md-doc) → indicateur de mobilité, pas un risque direct.
Règle de tri si tu dois choisir quoi rotater en premier
- Ce qui donne admin (GitHub orgs, Cloudflare API, AWS IAM, Privy app secrets, registrar).
- Ce qui donne prod (SSH Hostkey, MongoDB/Postgres admin, Railway).
- Ce qui permet signer/forger (JWT, webhook secrets Banxa/LiveKit,
REFERRAL_CLAIM_PRIVATE_KEY). - Le reste (Sentry, GA4, Tawk.to, Yandex, NewsData, Mobula, Financiya).