Retirer les secrets buildtime de l app Coolify et revoquer la cle PayPerQ sans consommateur #29
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/vps-health-api#29
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Contexte
L'app Coolify
vps-health-api(uuidu8000gsg044wsk0oo0w884ok) porte trois secrets enis_buildtime=true. Coolify les passe en build args : leur valeur finit en clair dansapplication_deployment_queues.logsa chaque deploiement (la-compagnie-maximus/docs/coolify-ops.md, section « Secrets en buildtime »). Drapeaux verifies le 2026-09-27 via l'API Coolify (aucune valeur lue) :PAYPERQ_API_KEYvps-health-20260419, aucun consommateurCHAT_DATABASE_URLchat_reader)CHAT_MODELHEALTH_TOKEN(
PORTetREPORTS_DIRsont en buildtime mais ne sont pas des secrets : hors scope.)Diagnostic
PAYPERQ_API_KEY:payperq-ops.mdenregistre vps-health-api comme proprietaire d'une cle dediee pour une « feature chat de l'API sante ». L'entree du journalsecret-rotation-ops.mddu 2026-04-19 (#109, Vague 2) decrit sa creation comme « reparation collaterale ». Or le code n'a jamais eu de chat :git log --all -S PAYPERQet-S CHAT_DATABASE_URLsont vides, aucune reference dans*.js,*.sh,Dockerfile. La cle est vivante, facturable, sans consommateur : revoquer, ne pas tourner.CHAT_DATABASE_URL/CHAT_MODEL: noms utilises par la-suite-booking (lib/chat-sql.ts, rolechat_reader). Aucune autre app Coolify ne porte ces cles. Le rolechat_readera eteDROPle 2026-08-12 lors du demantelement de booking : si l'URL le vise, l'identifiant est mort. A confirmer (voir etape 1).HEALTH_TOKENpreview : aucun deploiement preview n'a jamais eu lieu (0pull_request_idsur les deploiements listes). La row n'a donc jamais fuite : correction du drapeau seulement, sans rotation.PAYPERQ_API_KEYetCHAT_DATABASE_URLen clair.GET /envsne prouve rien. Les verifications de contenu passent par le conteneur.Travail a faire
PAYPERQ_API_KEYrenseignee ou non (longueur),CHAT_DATABASE_URL-> utilisateur + hote + base seulement ;zgkgc8soo8k4k44woo00ckg8) :chat_reader(ou l'utilisateur trouve) present danspg_roles?coolify-db: lignes deapplication_deployment_queuesde cette app dontlogscontientPAYPERQ_API_KEY/CHAT_DATABASE_URL.CHAT_DATABASE_URLest un role vivant : repasser en rotation (ALTER USER ... PASSWORD) et identifier son consommateur legitime avant toute suppression.PAYPERQ_API_KEY,CHAT_DATABASE_URL,CHAT_MODELde l'app (les 2 rows de chacune).HEALTH_TOKENenis_buildtime=false; verifier par(key, is_preview), pas parkey.vps-health-20260419sans la remplacer (DELETE /keys/{id}avec lecredit-iddepuis le gestionnaire de mots de passe, ou dashboard ppq.ai). Voirpayperq-ops.md.vps-deploy-booking-2026-04-14(id 12) via l'UI Forgejo (l'API refuse sanswrite:user) ;myprojects.geoapify.com, pas d'API) ;vercel env rm PAYPERQ_KEY_BOOKING production;shred -u /root/booking-env-preserved-20260812sur le VPS.application_deployment_queues(coolify-db), apres les revocations.GET /envsne montre plus aucun secret enbuildtime=true; les 5 routes de lecture repondent 200.la-compagnie-maximus:docs/payperq-ops.md: retirer la ligne vps-health-api du registre ; noter la revocation de la cle booking (retirer l'avertissement « n'est pas revoquee ») ;docs/secret-rotation-ops.md: entree de journal datee pour les revocations, et rectification datee de la « reparation collaterale » du 2026-04-19 (le chat n'a jamais existe) sans reecrire l'entree historique ; corriger la note « Important (collateral) » (ligne ~324) ;docs/coolify-ops.md: tableau « Secrets en buildtime » a jour pour vps-health-api.Hors scope
PORT/REPORTS_DIRen buildtime : non secrets.Criteres d'acceptation
PAYPERQ_API_KEY,CHAT_DATABASE_URL,CHAT_MODELabsentes de l'app (2 rows chacune)HEALTH_TOKENpreview enis_buildtime=falsevps-health-20260419revoquee (absente deGET /keys)/root/booking-env-preserved-20260812detruit ;PAYPERQ_KEY_BOOKINGretiree de Vercel/envspropre, 5 routes de lecture en 200Complexite
Medium, entierement manuelle (credit-id PayPerQ, sudo VPS, dashboards Geoapify / Forgejo / ppq.ai). Hors autopilot. Aucun code dans ce depot.
Archive avant reecriture (/analyze du 2026-09-27).
La premisse «
PAYPERQ_API_KEYetCHAT_*sont orphelines, venues d'une autre app » est a moitie fausse.CHAT_DATABASE_URL/CHAT_MODELportent bien les noms de la-suite-booking. En revanche,PAYPERQ_API_KEYest enregistree dansla-compagnie-maximus/docs/payperq-ops.mdcomme cle dediee a vps-health-api (vps-health-20260419, creee lors de la « reparation collaterale » de la rotation #109) pour une « feature chat » que le code n'a jamais eue (git log -S PAYPERQvide). Consequence : il faut une revocation seche, pas une rotation. Le corps est reecrit en consequence.Corps d'origine
Trois variables de l app Coolify
vps-health-api(uuidu8000gsg044wsk0oo0w884ok) sont enis_buildtime=truealors qu elles portent (ou peuvent porter) un secret. Coolify les passe alors en build args, et leur valeur finit en clair dansapplication_deployment_queues.logsa chaque deploiement. Voirla-compagnie-maximus/docs/coolify-ops.md, section « Secrets en buildtime ».Releve le 2026-09-27 via l API Coolify (drapeaux seulement, aucune valeur lue) :
PAYPERQ_API_KEYCHAT_DATABASE_URLHEALTH_TOKENLa row production de
HEALTH_TOKENest correcte (buildtime=false).CHAT_MODEL,PORTetREPORTS_DIRsont aussi en buildtime mais ne sont pas des secrets.Constat aggravant :
PAYPERQ_API_KEYetCHAT_*sont orphelinesAucune reference dans le code (
grepsur*.js,*.sh,Dockerfile,*.md) : l API est a 0 dependance runtime et n a ni chat ni base de donnees. Ces variables viennent vraisemblablement d une autre app (copie de configuration ?). Elles n ont rien a faire ici, et y etre en buildtime les expose a chaque deploiement de cette app pour aucun benefice.Premiere observation : 2026-08-18 (commentaire de #16). Depuis, au moins deux deploiements (2026-09-25 et
co4k0k8888gow4o84gk8kgkcle 2026-09-26) ont ecrit ces valeurs dans les logs.Criteres d acceptation
PAYPERQ_API_KEYetCHAT_DATABASE_URL(et confirmer qu elle porte ses propres copies) avant toute suppressionPAYPERQ_API_KEY,CHAT_DATABASE_URL,CHAT_MODELde l appvps-health-api(les 2 rows de chacune)HEALTH_TOKENenis_buildtime=false(verifier par(key, is_preview), pas parkey)CHAT_DATABASE_URL: elles ont fuite dans les logs, les retirer de l app ne suffit pas. Suivredocs/secret-rotation-ops.mdet mettre a jour l app proprietaireapplication_deployment_queues(ou documenter pourquoi on ne le fait pas)GET /envsne montre plus aucun secret enbuildtime=true; les 5 routes de lecture repondent 200buildtime=true, rows preview comprises) et ouvrir une issue par app toucheeNotes
HEALTH_TOKENpreview n est utilise que si les preview deploys sont actives ; s il porte la meme valeur que la row production, la fuite concerne le token de production. A verifier, et tourner si c est le cas (rotation conjointe avecHOSTS_INGEST_TOKEN, cf. #16).Retirer les secrets exposes en buildtime dans l app Coolify (PAYPERQ, CHAT_DATABASE_URL, HEALTH_TOKEN preview)to Retirer les secrets buildtime de l app Coolify et revoquer la cle PayPerQ sans consommateurAvancement 2026-09-27 (/fix-issue).
Fait
PAYPERQ_API_KEY,CHAT_DATABASE_URL,CHAT_MODELsupprimees de l'app (production + preview, 6 DELETE en 200).HEALTH_TOKENest supprimee plutot que patchee. Les valeurs Coolify sont write-only (GET /envsne les renvoie pas) : un PATCH du drapeau aurait exige de renvoyer la valeur du token de production. La row etait inerte (aucun preview deploy). Seule la row production reste, enruntime=true, buildtime=false.GET /envsapres coup : plus aucun secret enbuildtime=true(restentPORTetREPORTS_DIR, non secrets).Pas encore redeploye, volontairement : le conteneur garde son ancien environnement, necessaire a la verif de l'etape 1 (contenu de
CHAT_DATABASE_URL). Le redeploy vient apres.Reste, manuel
vercel env rm PAYPERQ_KEY_BOOKING production, puisshreddu.envpreserveEtape 1 (verifs VPS, 2026-09-27, metadonnees seulement) :
u8000gsg044wsk0oo0w884ok-000827029031:PAYPERQ_API_KEYrenseignee (25 caracteres) ;CHAT_DATABASE_URL->user=chat_reader host=10.0.1.8:5432 db=/booking.zgkgc8soo8k4k44woo00ckg8, roles de login :logto,logto_tenant_logto_admin,logto_tenant_logto_default,maximus_api,postgres,roadtrip,simpl_sante,simpl_sante_ro,simpliste.chat_readerabsent (DROP du 2026-08-12 confirme) ; la basebookingn'existe plus non plus.CHAT_DATABASE_URLest donc un identifiant mort : pas de rotation.application_deployment_queuesde cette app : 2 lignes, toutes deux contiennentPAYPERQ_API_KEYetCHAT_DATABASE_URL:d84okkgc80wkkcskskgsgogo(2026-09-25 01:41:58)co4k0k8888gow4o84gk8kgkc(2026-09-27 00:08:27)Consequence : seule la cle PPQ
vps-health-20260419est un secret vivant expose. La purge des 2 lignes suit sa revocation.Etape 7 : redeploy
u8wswsgwckw4g804400kos0o(2026-09-27)finished. Les variablesPAYPERQ_API_KEY/CHAT_*ne sont plus injectees dans le conteneur, et ce deploiement n'a plus aucune valeur secrete a ecrire dans les logs.Routes de lecture, avec token :
/health200,/defenseurs200,/defenseurs/state200,/reports/scans?date=2026-09-27200,/hosts200,/defenseurs/findings?project=roadtrip200 (project=vps-health-api-> 404 attendu, projet absent deagents-map.json).Reste : revocations (etapes 4-5), puis purge des 2 lignes
d84okkgc80wkkcskskgsgogoetco4k0k8888gow4o84gk8kgkc(etape 6) et docs (etape 8).Etape 5, 2026-09-27 :
PAYPERQ_KEY_BOOKINGretiree de Vercel production (vercel env rm, aucun consommateur danssrc/). RestentPAYPERQ_API_KEY+ 3PAYPERQ_KEY_*d'agents, inchangees.PAYPERQ_CREDIT_IDdela-compagnie-maximus/.env.localest refuse parGET https://api.ppq.ai/keys(Invalid credit ID). La copie locale est perimee ; la valeur valide vit dans le gestionnaire de mots de passe. A faire avec elle, ou via le dashboard ppq.ai.GET /users/maximus/tokensrepondauth requireda une auth par token (comportement deja documente le 2026-08-12). A revoquer dans l'UI Forgejo : Parametres -> Applications -> Jetons d'acces.Cloture 2026-09-27. Tous les criteres sont remplis.
vps-health-20260419et cle PPQ booking (faites par Max), token Forgejo id 12 (UI, Max), cle Geoapify...c94281(dashboard, Max ; l'ancienne cle repond401, verifie).PAYPERQ_KEY_BOOKINGretiree de Vercel./root/booking-env-preserved-20260812detruit (shred -u, absent ensuite).DELETE 2surapplication_deployment_queues(d84okkgc...,co4k0k88...). Reste le seul deploiementu8wswsgwckw4g804400kos0o, sans aucune des deux cles.PAYPERQ_API_KEYetait masquee par Coolify (<REDACTED>) dans les deux lignes, donc jamais en clair ;CHAT_DATABASE_URLetait en clair mais pointait verschat_reader, role deja droppe. Aucun secret vivant n'a donc fuite en clair ; la revocation de la cle PPQ reste justifiee (cle facturable sans consommateur).la-compagnie-maximus@7d9a1f2(payperq-ops, geoapify-ops, secret-rotation-ops avec rectification datee du 2026-04-19, coolify-ops).la-compagnie-maximus#170.