Files
IdeA/.ideai/tickets/72/issue.md
Blomios f915635e07 chore(ideai): ouverture de #72 (confiance reverse proxy sans effet réel)
- #72 ouvert en priorité haute, bloquant #68 : `--trust-reverse-proxy` n'est lu
  que dans `ServerConfig::validate()` pour exiger sa propre présence — le serveur
  ne parse jamais `X-Forwarded-*`. C'est un drapeau d'intention pur, qui donne un
  faux sentiment de protection. Le ticket porte aussi B0 (le bug de port effectif
  sur le chemin CLI `run_server`), `trusted_proxies` + `--trusted-proxy`, le
  guard runtime et les événements de diagnostic.
- Journal des tâches de fond : complétions enregistrées.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 18:50:57 +02:00

4.7 KiB

id, number, title, status, priority, sprint, links, agentRefs, createdBy, updatedBy, createdAt, updatedAt, version
id number title status priority sprint links agentRefs createdBy updatedBy createdAt updatedAt version
0fba0a7f-8f04-460e-b81a-93790e10b066 72 Sécurité : donner un effet réel à la confiance reverse proxy (--trust-reverse-proxy est un drapeau creux) open high null
target kind
#68 blocks
target kind
#71 relatesTo
target kind
#65 relatesTo
kind agent_id
agent a6ced819-b893-4213-b003-9e9dc79b9641
kind agent_id
agent a6ced819-b893-4213-b003-9e9dc79b9641
1784218596269 1784218596269 1

Vulnérabilité de conception existante, dans le mode CLI d'aujourd'hui — indépendante de #68. Trouvée par Git pendant la mise en place de #68, confirmée et cadrée par Architect.

Le constat. --trust-reverse-proxy n'a aucun effet à l'exécution. Vérifié dans crates/web-server/src/lib.rs : le champ n'est lu qu'en ligne 192, dans ServerConfig::validate(), pour exiger sa propre présence quand allow_remote est vrai. Le serveur ne parse jamais X-Forwarded-*. C'est un drapeau d'intention pur.

Le problème. validate() valide une configuration, pas la réalité : rien ne vérifie qu'un proxy est réellement devant le serveur. Binder 0.0.0.0 avec les trois drapeaux, sans aucun proxy, satisfait validate() et sert du HTTP en clair au monde entier. La trilogie allow_remote + origine HTTPS + trust_reverse_proxy DÉCLARE une topologie sécurisée, elle ne la GARANTIT pas.

Verdict Architect : « la trilogie actuelle n'est pas un invariant de sécurité, c'est seulement une déclaration d'intention ». Aggravé par #68 : en CLI, taper trois drapeaux est un acte délibéré d'opérateur ; dans un panneau desktop, cocher un bouton ne l'est pas. Le drapeau donnerait un faux sentiment de protection en un clic.

Invariant runtime corrigé (Architect).

  • allow_remote=true signifie : mode public accepté UNIQUEMENT derrière un proxy HTTPS déclaré.
  • Les headers X-Forwarded-* ne sont fiables QUE si le peer_addr réseau est un proxy autorisé — vérifier le pair AVANT de leur faire confiance.
  • X-Forwarded-Proto: https exigé en mode remote.
  • X-Forwarded-Host (ou équivalent) doit correspondre à public_origin.
  • X-Forwarded-For ne doit JAMAIS servir à autoriser une requête — spoofable, log uniquement.
  • Proxy sur cette machine : bind loopback, peer forcément loopback, trust_reverse_proxy reste acceptable.
  • Proxy sur une autre machine : bind LAN autorisé SEULEMENT avec un proxy explicite (--trusted-proxy 192.168.1.10 ou CIDR). Toute requête dont le peer_addr est hors allowlist est refusée, même porteuse de X-Forwarded-Proto: https.

Conséquence produit : le mode desktop « proxy autre machine » ne peut pas être un clic magique. Il doit demander l'IP/CIDR du proxy autorisé — ce n'est pas une « listen address » mais un contrôle de sécurité compréhensible : « quelle machine a le droit de parler au serveur IdeA ? ».

Lots (Architect).

  • B1 config : trusted_proxies: Vec<IpNet/Cidr> dans ServerConfig, flag CLI --trusted-proxy, DTO desktop équivalent.
  • B2 runtime guard : en tête du handling HTTP/WS, vérifier peer_addr, X-Forwarded-Proto=https, host public conforme.
  • B3 diagnostics : événements untrustedProxyPeer, forwardedProtoRejected, forwardedHostRejected (à croiser avec #71).
  • B4 docs : exemples séparés proxy local vs proxy autre machine.

Points de vérité QA.

  • 0.0.0.0 + allow_remote + public_origin + trust_reverse_proxy sans trusted proxy → REFUSÉ.
  • peer non autorisé vers bind LAN → rejeté.
  • peer autorisé mais X-Forwarded-Proto=http → rejeté.
  • peer autorisé + https + host conforme → passe.
  • origine API non conforme → toujours 403.
  • aucun test ne fait confiance à X-Forwarded-For.

Compat / migration. Garder --trust-reverse-proxy pour la CLI, mais le déclasser en option de mode : il ne suffit plus pour un bind non-loopback. Chemin de migration à choisir (refus au démarrage vs refus runtime).

⚠️ Impact utilisateur réel connu : l'installation actuelle de l'utilisateur (bind 192.168.1.75:17373 + trilogie, proxy sur une autre machine, exposé via https://idea.anthonybouteiller.ovh) sera refusée par la validation corrigée tant qu'elle ne déclare pas --trusted-proxy. Le chemin de migration doit être explicite et le message d'erreur doit dire quoi faire, pas seulement refuser.

Ordre imposé par Architect : #68 core (B1 shared-core) peut continuer, il n'est pas exposé utilisateur. Mais #72 doit être mergé dans develop AVANT feature/ticket68-embedded-server-panel — pas de panneau remote avant ce durcissement.