Le depot que trente satellites clonent livrait un RCE critique #36

Merged
nicolas-fryder merged 2 commits from nicolas-fryder/dev into main 2026-10-07 08:11:14 +00:00 AGit

next releve a ^16.3.6 (GHSA-vcvr-r3jv-pc5j, RCE CRITICAL), @grpc/grpc-js a >=1.14.5 (GHSA-m9gg-hp2v-232j, HIGH, arrive par @eqs/telemetry), multer a ^2.4.0. Et fast-uri resserre en ^3.1.8 : la premiere version en >=3.1.8 substituait un majeur qu'ajv ne declare pas.

next releve a ^16.3.6 (GHSA-vcvr-r3jv-pc5j, RCE CRITICAL), @grpc/grpc-js a >=1.14.5 (GHSA-m9gg-hp2v-232j, HIGH, arrive par @eqs/telemetry), multer a ^2.4.0. Et fast-uri resserre en ^3.1.8 : la premiere version en >=3.1.8 substituait un majeur qu'ajv ne declare pas.
`eqs coolify verify --up` écrit un `.env` qui est `.env.example` TEL QUEL, empile
`docker-compose.repetition.yml` s'il existe, construit et attend `healthy` cent
quatre-vingts secondes.

Ce dépôt n'avait pas de surcouche — contrairement à `eqs-demo`, qui en a une
précisément pour ça — et son `.env.example` laisse `SERVICE_NAME` vide À DESSEIN :
un clone doit se nommer, sinon deux clones parlent à la même base sans que rien ne
le dise (`eqs-platform` #62). Le compose écrit `SERVICE_NAME: ${SERVICE_NAME}`
sans repli, donc le conteneur recevait une chaîne vide et `@eqs/config` refusait
de démarrer sur « SERVICE_NAME est requise ». Même chose pour `DATABASE_URL`, qui
vise `localhost:55400` — l'adresse du poste, c'est-à-dire le conteneur lui-même
vu de l'intérieur.

Et le verdict de `--up` pour tout ça était « le conteneur n'est jamais devenu
sain », après trois minutes d'attente et une construction d'image, sans nommer une
seule variable. Le dépôt que trente satellites clonent livrait donc une porte que
lui-même ne pouvait pas franchir.

La correction va dans la surcouche et nulle part ailleurs : `.env.example` garde
son nom et ses secrets vides, ce qui est sa raison d'être. La surcouche ne part
jamais en production — Coolify ne lit que `docker-compose.coolify.yml`.

`@eqs/testing` gagne dans la foulée le contrôle qui le dit sans Docker :
`coolify.repetition-demarrable` reconstitue cet environnement et le passe par les
portes que l'application franchira, en nommant la variable. Mesuré : SANS ce
fichier, il rougit sur `api ne démarrerait pas en répétition : SERVICE_NAME est
requise` ; avec, il se tait. C'est la chasse 21 du socle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Trois avis relevés, dont deux que la porte de ce dépôt ne pouvait pas montrer
tant que personne ne touchait un manifeste.

## `next` : RCE CRITICAL

GHSA-vcvr-r3jv-pc5j — exécution de code à distance dans `next/og ImageResponse`.
Vulnérable `>=16.2.0 <16.3.6` ; `apps/web` était en `^16.3.4`, résolu 16.3.4.
Porté à `^16.3.6`, résolu **16.3.7**.

Ce qui rend ce dépôt-ci particulier : **un clone neuf part de son verrou.** Un
intervalle permissif ne protège rien quand le verrou committé épingle le
vulnérable — donc chaque satellite créé depuis la sortie de l'avis naissait avec
le RCE, sans que personne n'ait rien fait de mal.

## `@grpc/grpc-js` : HIGH, et il vient du socle

GHSA-m9gg-hp2v-232j — dans certaines configurations, `getAuthContext` rend des
certificats **non autorisés** comme s'ils l'étaient. Plus GHSA-f596-whhp-79r4,
LOW, sur la même plage. Corrigé en 1.14.5.

Le chemin est ce qui compte :

    @eqs/auth > @eqs/telemetry > @opentelemetry/sdk-node
              > @opentelemetry/exporter-{logs,metrics}-otlp-grpc
              > @opentelemetry/otlp-grpc-exporter-base > @grpc/grpc-js

**Tout satellite qui pousse sa télémétrie en gRPC est concerné**, et l'override
posé ici ne protège que ce dépôt et ses clones. Le correctif de fond est de
relever les intervalles OpenTelemetry de `@eqs/telemetry` — remonté au socle,
pas contourné en silence, et la ligne porte son « à retirer quand ».

## `multer` : une borne d'override qui s'était périmée

`^2.3.0` couvrait trois avis. Un quatrième (GHSA-3pph-fpjx-jg34) porte sur
`>=2.2.0 <2.4.0` : la borne ne suffisait plus. **Une borne d'override se périme
sans que personne ne touche au code**, et c'est l'argument le plus solide pour
ne pas laisser un audit dépendre de ce qu'il y a dans l'index.

## Un défaut dans mon propre correctif, rattrapé

`fast-uri` a d'abord été écrit `'>=3.1.8'`. Il a résolu **4.2.1**, alors qu'`ajv`
déclare `fast-uri: ^3.0.1` — un majeur substitué en silence dans la résolution
d'URI d'un validateur de schémas, **porte verte**. C'est exactement la forme de
défaut qu'un override est censé éviter. Resserré en `'^3.1.8'`, résolu 3.1.8.

Un override reste dans le majeur que le consommateur déclare.

## Vérifié

`eqs audit` : 0 alerte high/critical en production, aucune alerte non dispensée.
`pnpm check` vert du premier passage.

**Pas de dispense, pour aucun des trois.** Les correctifs existent ; dispenser un
RCE critique corrigeable serait un contournement avec une date dessus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
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
Infrastructure/eqs-satellite-template!36
No description provided.