Durcir la comparaison du HEALTH_TOKEN (timing-safe) #17
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#17
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
Le chemin de lecture compare encore le token par egalite de chaine directe (
index.js,checkAuth()) :Cette comparaison s'arrete au premier octet different : le temps de reponse fuit la longueur et le prefixe du
HEALTH_TOKEN. Le chemin d'ingestion passe deja partokenMatches()(timingSafeEqual sur empreintes SHA-256, livre avec #13). Le commentaire au-dessus detokenMatches()renvoie explicitement a cette issue.Premisse verifiee le 2026-09-27 : le corps initial citait
auth !==; depuis le refactor de la tableROUTES(fedb1c8), la comparaison vit danscheckAuth()sous la formeheader === .... Le defaut est identique.Travail a faire
checkAuth(): un seul chemin pour les deuxtokenKind—typeof header === "string" && header.startsWith("Bearer ") && tokenMatches(header.slice(7), expected). Seulexpectedvarie, comme le demande la regle du point de controle unique.tokenMatches()(retirer « Deliberately scoped to the new write path ... issue #17 »).__tests__/auth.test.js(« compared byte for byte » devient « compared in constant time via tokenMatches »).Bearer,Bearer(espace, token vide). Tous 401.index.jset echoue si une comparaison directe=== \Bearerreapparait (meme style que le test qui epingle leCOPYdu Dockerfile dansagent.test.js`). Un test de timing serait flaky ; l'epingle est le seul garde fiable.CLAUDE.md(section Routage et auth) :tokenMatches()protege desormais les deux tokens ; retirer la mention « uniquement le chemin d'ingestion ». Mettre a jour le compte de tests.Fichiers concernes
index.js—checkAuth()et commentaire detokenMatches()__tests__/auth.test.js— quasi-rates + epingle sourceCLAUDE.md— section Routage et auth, compte de testsSurface de test
__tests__/auth.test.js(401 sans en-tete / mauvais token / en-tetes malformes sur les routes de lecture, fail-closed, cloisonnement des deux tokens, 404 avant 401),__tests__/state.test.js,__tests__/hosts.test.js(401 croises),test-curl.sh(niveau socket).Bearersensible a la casse. Aucun test existant ne doit bouger.Criteres d'acceptation
HEALTH_TOKENpasse partokenMatches()timingSafeEqualfuiterait la longueur (GHSA-376v-xgjx-7mfr)npm testetbash test-curl.shverts/health,/defenseurs,/defenseurs/state,/defenseurs/findings?project=...,/reports/scans?date=...,/hosts) en 200 avec token et 401 sans ; carte admin Vercel chargeeComplexite estimee
Simple — une ligne de logique, le helper existe deja.
Decisions prises
Spec source
la-compagnie-maximus/spec-plan-monitoring-postes.md + spec-decisions-monitoring-postes.md (Issue 8)