security: HEALTH_TOKEN injecte en build ARG par Coolify, fuite en clair dans les logs de deploiement #4

Closed
opened 2026-04-29 01:05:14 +00:00 by maximus · 0 comments
Owner

Contexte

Pendant l'incident du 2026-04-28 (panne des cards Sante VPS + Defenseurs sur lacompagniemaximus.com/admin), inspection des logs de deploiement Coolify (application_deployment_queues.logs) : HEALTH_TOKEN est stocke en clair dans le Dockerfile genere par Coolify et donc dans la DB Coolify.

Extrait observe (deployment_uuid 9fe696fc-5076-4c19-8a11-ead431526058) :

ARG HEALTH_TOKEN=<64-hex-secret-en-clair>
ARG PAYPERQ_API_KEY=<REDACTED>

Coolify redacte automatiquement les noms qui matchent un pattern (API_KEY, SECRET, etc.) mais pas HEALTH_TOKEN. Le secret apparait donc en clair :

  • dans application_deployment_queues.logs (DB Coolify)
  • dans le contexte de build Docker (cache de couches buildkit)
  • potentiellement dans tout dump/backup de la DB Coolify

Cause racine

Cote Coolify, HEALTH_TOKEN a is_buildtime=true ET is_runtime=true dans environment_variables. La variable est donc passee comme build ARG en plus du runtime env. Or index.js ne lit HEALTH_TOKEN qu'au runtime — is_buildtime n'est pas necessaire.

-- Etat actuel (resourceable_id=1, resourceable_type='App\Models\Application'):
key          | is_buildtime | is_runtime
HEALTH_TOKEN | t            | t
PAYPERQ_API_KEY | t         | t

Decouvertes analyse (2026-05-03)

Verification du code vps-health-api : conforme runtime-only, bug 100% dans Coolify.

  • vps-health-api/index.js:8 : TOKEN = process.env.HEALTH_TOKEN lu uniquement au demarrage
  • Dockerfile : zero ARG, zero ENV declare
  • package.json : pas de build step (scripts.start = "node index.js")
  • Aucune autre app Coolify du monorepo n'est vulnerable :
    • maximus-api/Dockerfile : zero ARG
    • feedback-api/Dockerfile : zero ARG
    • la-suite-booking/Dockerfile : ARG NEXT_PUBLIC_* uniquement (publics par design Next.js)
    • simpl-liste/web/Dockerfile : zero ARG
  • Doc la-compagnie-maximus/docs/coolify-ops.md a deja une section runtime-only secrets (commit 7044c14, avril 2026) mais reference uniquement maximus-api. A etendre pour generaliser.

Travail a faire (1 issue, 4 cases)

  • Coolify : HEALTH_TOKEN et PAYPERQ_API_KEY -> is_buildtime=false (PATCH environment_variables sur l'application Coolify, ou via UI)
  • Rotation : generer nouveau HEALTH_TOKEN, mettre a jour cote Coolify ET Vercel (VPS_HEALTH_TOKEN) simultanement — mismatch = panne admin cards (cf. incident 2026-04-28 qui a dure 8 jours)
  • Purge : DELETE FROM application_deployment_queues WHERE created_at < <date-rotation> AND application_id = <vps-health-api-id> (ou tronquer la table entiere si pas de retention necessaire). Idem cote backups Coolify si retention longue.
  • Doc : etendre la-compagnie-maximus/docs/coolify-ops.md — generaliser le pattern runtime-only a toute app dont le secret est lu uniquement a process.env.* au demarrage. Ajouter vps-health-api a l'exemple.

Fichiers concernes

  • Coolify (config externe via API ou UI, hors repo)
  • ~/claude-code/la-compagnie-maximus/docs/coolify-ops.md — extension section secrets
  • ~/claude-code/vps-health-api/.env.example — note inline "MUST be runtime-only on Coolify, never buildtime ARG"
  • ~/claude-code/vps-health-api/CLAUDE.md — section Auth, ajouter avertissement runtime-only

Surface de test

  • Aucun test code (issue ops)
  • Verification post-action : declencher un nouveau deploiement, puis grep HEALTH_TOKEN dans les nouveaux logs Coolify -> doit etre absent ou <REDACTED>

Criteres d'acceptation

  • HEALTH_TOKEN absent en clair dans application_deployment_queues.logs apres prochain deploy
  • Cards admin lacompagniemaximus.com/admin toujours fonctionnelles apres rotation (test bout-en-bout)
  • coolify-ops.md etendu, lu et valide
  • Anciens logs purges

Complexite

Simple — ~30 min total, aucun code a ecrire, mais coordination Vercel <-> Coolify obligatoire pour la rotation (sinon les cards retombent en panne).

Notes

  • Le bug Coolify upstream (redaction trop laxiste sur HEALTH_TOKEN, PAYPERQ_API_KEY) est un autre sujet ; on s'en passe en supprimant is_buildtime.
  • L'ancien token a aussi fuite via un mismatch Vercel/VPS qui a dure 8 jours (rotation #109 LCM, voir incident de ce jour).
## Contexte Pendant l'incident du 2026-04-28 (panne des cards Sante VPS + Defenseurs sur `lacompagniemaximus.com/admin`), inspection des logs de deploiement Coolify (`application_deployment_queues.logs`) : **`HEALTH_TOKEN` est stocke en clair** dans le Dockerfile genere par Coolify et donc dans la DB Coolify. Extrait observe (deployment_uuid `9fe696fc-5076-4c19-8a11-ead431526058`) : ``` ARG HEALTH_TOKEN=<64-hex-secret-en-clair> ARG PAYPERQ_API_KEY=<REDACTED> ``` Coolify redacte automatiquement les noms qui matchent un pattern (`API_KEY`, `SECRET`, etc.) mais pas `HEALTH_TOKEN`. Le secret apparait donc en clair : - dans `application_deployment_queues.logs` (DB Coolify) - dans le contexte de build Docker (cache de couches buildkit) - potentiellement dans tout dump/backup de la DB Coolify ## Cause racine Cote Coolify, `HEALTH_TOKEN` a `is_buildtime=true` ET `is_runtime=true` dans `environment_variables`. La variable est donc passee comme build ARG en plus du runtime env. Or `index.js` ne lit `HEALTH_TOKEN` qu'au runtime — `is_buildtime` n'est pas necessaire. ```sql -- Etat actuel (resourceable_id=1, resourceable_type='App\Models\Application'): key | is_buildtime | is_runtime HEALTH_TOKEN | t | t PAYPERQ_API_KEY | t | t ``` ## Decouvertes analyse (2026-05-03) Verification du code vps-health-api : **conforme runtime-only**, bug 100% dans Coolify. - `vps-health-api/index.js:8` : `TOKEN = process.env.HEALTH_TOKEN` lu uniquement au demarrage - `Dockerfile` : zero `ARG`, zero `ENV` declare - `package.json` : pas de build step (`scripts.start = "node index.js"`) - Aucune autre app Coolify du monorepo n'est vulnerable : - `maximus-api/Dockerfile` : zero ARG - `feedback-api/Dockerfile` : zero ARG - `la-suite-booking/Dockerfile` : `ARG NEXT_PUBLIC_*` uniquement (publics par design Next.js) - `simpl-liste/web/Dockerfile` : zero ARG - Doc `la-compagnie-maximus/docs/coolify-ops.md` a deja une section runtime-only secrets (commit `7044c14`, avril 2026) mais reference uniquement `maximus-api`. A etendre pour generaliser. ## Travail a faire (1 issue, 4 cases) - [ ] **Coolify** : `HEALTH_TOKEN` et `PAYPERQ_API_KEY` -> `is_buildtime=false` (PATCH `environment_variables` sur l'application Coolify, ou via UI) - [ ] **Rotation** : generer nouveau `HEALTH_TOKEN`, mettre a jour cote Coolify ET Vercel (`VPS_HEALTH_TOKEN`) **simultanement** — mismatch = panne admin cards (cf. incident 2026-04-28 qui a dure 8 jours) - [ ] **Purge** : `DELETE FROM application_deployment_queues WHERE created_at < <date-rotation> AND application_id = <vps-health-api-id>` (ou tronquer la table entiere si pas de retention necessaire). Idem cote backups Coolify si retention longue. - [ ] **Doc** : etendre `la-compagnie-maximus/docs/coolify-ops.md` — generaliser le pattern runtime-only a toute app dont le secret est lu uniquement a `process.env.*` au demarrage. Ajouter `vps-health-api` a l'exemple. ## Fichiers concernes - Coolify (config externe via API ou UI, hors repo) - `~/claude-code/la-compagnie-maximus/docs/coolify-ops.md` — extension section secrets - `~/claude-code/vps-health-api/.env.example` — note inline "MUST be runtime-only on Coolify, never buildtime ARG" - `~/claude-code/vps-health-api/CLAUDE.md` — section Auth, ajouter avertissement runtime-only ## Surface de test - Aucun test code (issue ops) - Verification post-action : declencher un nouveau deploiement, puis `grep HEALTH_TOKEN` dans les nouveaux logs Coolify -> doit etre absent ou `<REDACTED>` ## Criteres d'acceptation - [ ] `HEALTH_TOKEN` absent en clair dans `application_deployment_queues.logs` apres prochain deploy - [ ] Cards admin `lacompagniemaximus.com/admin` toujours fonctionnelles apres rotation (test bout-en-bout) - [ ] `coolify-ops.md` etendu, lu et valide - [ ] Anciens logs purges ## Complexite **Simple** — ~30 min total, aucun code a ecrire, mais coordination Vercel <-> Coolify obligatoire pour la rotation (sinon les cards retombent en panne). ## Notes - Le bug Coolify upstream (redaction trop laxiste sur `HEALTH_TOKEN`, `PAYPERQ_API_KEY`) est un autre sujet ; on s'en passe en supprimant `is_buildtime`. - L'ancien token a aussi fuite via un mismatch Vercel/VPS qui a dure 8 jours (rotation #109 LCM, voir incident de ce jour).
maximus added the
source:human
status:triage
type:security
labels 2026-04-29 01:05:22 +00:00
maximus added
status:ready
and removed
status:triage
labels 2026-05-03 19:52:07 +00:00
maximus added the
status:in-progress
label 2026-05-03 19:56:05 +00:00
maximus added
status:approved
and removed
status:in-progress
status:ready
labels 2026-05-03 19:57:19 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/vps-health-api#4
No description provided.