33800 Docs

← Retour

Revue des correctifs d'audit — TERMINÉE

Date : 15/02/2026 Methode : Revue un par un avec validation utilisateur avant chaque action Rapport source : ~/propositions/15-02-2026-10-10-audit-rapport-final-verifie.md


Progression

Total : 146/146 findings revus et valides

Implémentation des correctifs — Progression

Migration DNS Pi-hole — TERMINÉE

connectors-api — TERMINÉ (20/22 correctifs)

ai-orchestrator — TERMINÉ (33/33 correctifs)

ulias-org — TERMINÉ (31/30 correctifs → 30/30 + C-13 encryption bonus)

ulias-org-web — TERMINÉ (21/25 correctifs)

Ordre d'implémentation global — BILAN :

  1. Migration DNS Pi-hole FAIT
  2. connectors-api FAIT (20/22 — C-13 N/A, C-15 N/A)
  3. ai-orchestrator FAIT (33/33 — tous correctifs implémentés)
  4. ulias-org FAIT (30/30 — tous correctifs implémentés)
  5. ulias-org-web FAIT (21/25 — C-10 reporté serveur, C-12/U-13 non nécessaires, U-10 vérifié OK)
  6. Correctifs reportés FAIT (6/6 implémentés — commit 2f8786c, a0f1aa7, 9cfc758, c1f4e15, 22cb3a0)
  7. Dashboard migration (nouveau projet) ← PROCHAIN

Decisions transversales

Migration DNS Pi-hole (VALIDÉE)

Migration dashboard projet GitLab (VALIDÉE)

Health check réel (VALIDÉE — tous projets)

CORS *.nowhere84.com (VALIDÉE — tous projets)

Auth API key interne (VALIDÉE — tous services internes)

Zéro fallback hardcodé (VALIDÉE — tous projets)

Coût estimé IA locale (VALIDÉE)


Decisions validees — connectors-api (22)

C-01 : verifyJWT() ne verifie pas la signature HMAC

Decision : VALIDE Correctif : Implementer verification HMAC-SHA256 avec crypto.createHmac('sha256', SUPABASE_JWT_SECRET). ~10 lignes dans verifyJWT().

C-02 : Fallback Supabase URL hardcode

Decision : VALIDE Correctif : Supprimer le fallback. Throw erreur explicite si URL non configuree dans l'instance.

C-03 : getUserFromRequest() sync ne gere pas les API keys

Decision : VALIDE — Simplification du code Correctif : Supprimer getUserFromRequest() completement. Tout migrer vers getAuthFromRequest() (un seul chemin d'auth). PAS de doublon de code.

C-04 : onRequest hook bypass pour routes hors /api/

Decision : VALIDE — Securite par ergonomie Correctif : Inverser la logique. Auth sur TOUTES les routes par defaut. Allowlist explicite pour les routes publiques : const PUBLIC_ROUTES = ['/health', '/api/oauth/callback']

C-05 : Pas de rate limiting sur login/register

Decision : VALIDE Correctif : Rate limiter simple sur login/register. Max 5 tentatives par IP par minute. Compteur en memoire avec Map<ip, {count, timestamp}>.

C-06 : Mot de passe Supabase en fallback hardcode

Decision : VALIDE Correctif : Supprimer le fallback. Throw erreur si variable d'env manque. Credential uniquement via conf.prod.gouroubleu.yml.

C-07 : Error handler 404 catch les erreurs applicatives

Decision : VALIDE Correctif : Separer les handlers : 404 pour routes inexistantes, 500 pour erreurs applicatives avec log de l'erreur reelle.

C-08 : Pas de validation body sur register

Decision : VALIDE Correctif : Validation via t.Object() d'Elysia. Email : present, non vide, format valide. Password : present, min 8 caracteres. Retour 422 si invalide.

C-09 : getUserFromRequest retourne null au lieu de throw

Decision : VALIDE — Lie a C-03 Correctif : getAuthFromRequest() (le seul chemin d'auth apres C-03) doit THROW 401 quand l'auth echoue, pas retourner null. Si le code s'execute, l'utilisateur est authentifie.

C-10 : NODE_TLS_REJECT_UNAUTHORIZED=0 en production

Decision : VALIDE Correctif : Identifier le service avec cert problematique (probablement GitLab local). Ajouter le cert comme CA trusted via NODE_EXTRA_CA_CERTS. Retirer NODE_TLS_REJECT_UNAUTHORIZED=0.

C-11 : OAuth state non verifie apres callback

Decision : VALIDE Correctif : Generer state aleatoire a l'initiation OAuth, stocker en memoire avec TTL court. Verifier au callback que le state recu correspond. Rejeter sinon.

C-12 : Deletion complete au lieu de soft-delete pour instances

Decision : VALIDE Correctif : Ajouter champ deleted_at (timestamp nullable). DELETE met deleted_at = now(). GET filtre WHERE deleted_at IS NULL. Optionnel : endpoint restore/purge.

C-13 : Pas de validation schema sur conf.prod.gouroubleu.yml

Decision : VALIDE Correctif : Validation dans smart-deploy (pas dans connectors-api). Verifier champs obligatoires, types, warning env vars manquantes. Refuser deploiement si schema invalide.

C-14 : Logging insuffisant sur les erreurs d'auth

Decision : VALIDE Correctif : console.warn() sur chaque echec d'auth avec : raison (token expire, signature invalide, API key inconnue), endpoint appele, timestamp.

C-15 : Session cleanup inexistant pour sessions expirees

Decision : VALIDE — Utiliser Redis Correctif : Remplacer Map en memoire par Redis. Cles session:{apiKey} avec EXPIRE = duree de vie JWT (ou 24h). Auto-expiration sans cron. Ajouter URL Redis dans conf.prod.gouroubleu.yml pour connectors-api.

C-16 : API keys stockees en clair dans Supabase

Decision : VALIDE Correctif : Hasher (SHA-256) avant stockage. Retourner la cle en clair UNE SEULE FOIS a la creation. Auth : hasher la cle recue et comparer. Migration : regenerer les API keys existantes.

C-17 : SSH connector password en clair dans config instance

Decision : VALIDE — ATTENTION : ne pas perdre la cle de chiffrement Correctif : Chiffrer credentials sensibles (AES-256-GCM) avec cle serveur (env var ENCRYPTION_KEY). Dechiffrer au moment de l'utilisation. Ne JAMAIS retourner les mots de passe dans les reponses API GET. Backup obligatoire de la cle de chiffrement dans un endroit separe (credentials.md + fichier protege PVE).

C-18 : Timeout SSH fixe 30s sans configuration

Decision : VALIDE Correctif : Garder 30s comme defaut. Utiliser le parametre timeout optionnel deja prevu dans le schema de /api/ssh/execute. S'assurer qu'il est bien passe a l'execution SSH reelle.

C-19 : Pas de pagination sur GET /api/user/instances

Decision : VALIDE — Tags globaux obligatoires Correctif : Query params ?limit=50&offset=0. Retourner { instances, total, limit, offset, all_tags }. all_tags = liste dedupliquee de TOUS les tags de TOUTES les instances (pas seulement la page courante).

C-20 : CORS allow_origin=* en production

Decision : VALIDE — Pattern *.nowhere84.com Correctif : Verifier dynamiquement origin.endsWith('.nowhere84.com'). Pas de liste de sous-domaines a maintenir.

C-21 : Pas de Content-Security-Policy header

Decision : VALIDE Correctif : Middleware global : X-Content-Type-Options: nosniff, X-Frame-Options: DENY, HSTS, CSP: default-src 'none'. ~5 lignes dans onAfterHandle.

C-22 : Health endpoint sans check de dependances

Decision : VALIDE — Pattern transversal tous projets + sidecars Docker Correctif : /health verifie Supabase + Redis + sidecars (wireguard, browser). Retour structuré { status, dependencies }. Timeout 2-3s par check. 503 si degraded, jamais crash.


Decisions validees — ai-orchestrator (33)

C-01 : Cloud tasks Anthropic sans tracking

Correctif : Set active_tasks, Semaphore(max_concurrent=5), cleanup au shutdown.

C-02 : TOCTOU budget Anthropic

Correctif : Reservation cout estime au demarrage job, ajustement au reel en fin de job, transaction atomique.

C-03 : Credentials Redis/Postgres hardcodes

Correctif : Env vars dans conf.prod.gouroubleu.yml, pas de fallback, erreur au demarrage si manque.

C-04 : Mode generate Ollama sans num_ctx

Correctif : Passer num_ctx dans generate aussi, defaut 8192.

C-05 : CORS allow_origins=["*"] + allow_credentials=True

Correctif : Pattern *.nowhere84.com (transversal).

C-06 : is_cloud calcule deux fois + cout IA locale

Correctif : Calculer is_cloud une seule fois. Ajouter calcul cout estime local (GPU watts × duree × prix kWh). Flag cost_type cloud/local_estimated.

C-07 : Docstring dit 1-5, code fait min(10)

Correctif : Approfondir — bornes dynamiques par GPU et modele. Supprimer valeurs magiques.

C-08 : httpx client reutilise 2h

Correctif : Classifier erreurs transitoires (retry backoff) vs fatales (fail immediat). Recreer client apres erreur connexion.

C-09 : SadTalker cleanup process SSH

Correctif : await process.wait() dans finally. process.kill() en cas d'annulation. Stocker ref process pour cleanup shutdown.

C-10 : Job poppe de Redis puis DB echoue = perdu

Correctif : Pattern claim : deplacer dans liste processing Redis avant pop. Ecrire DB. Retirer de processing apres confirmation.

C-11 : queue_sync jamais appele au demarrage

Correctif : Appeler queue_sync() au demarrage avant de traiter des jobs. Re-queuer les jobs orphelins.

C-12 : Requeue sans compteur retry

Correctif : Incrementer retry_count a chaque requeue. MAX_RETRIES=3, au-dela → failed definitif.

C-13 : run_ssh_command timeout sans proc.kill()

Correctif : process.kill() + await process.wait() au timeout. Timeout configurable par job (defaut 60s). Pattern try/finally systematique.

C-14 : Watchdog parse "N/A" → desactive

Correctif : Verifier si valeur est "N/A" avant conversion. Skip metrique, continuer watchdog. Logger warning. Jamais desactiver watchdog a cause d'un parsing.

C-15 : 13 bare except

Correctif : Remplacer par except Exception: (exclut CancelledError, SystemExit). Idealement typer chaque except. Logger warning dans chaque bloc.

C-16 : Upload file.read() sans limite

Correctif : Verifier Content-Length, MAX_UPLOAD_SIZE_MB configurable (defaut 500), lire en streaming par chunks, 413 si depasse.

C-17 : Aucune authentification

Correctif : Auth API key via env var API_KEY. Header Authorization: Bearer. Pattern transversal services internes.

C-18 : costs_summary year/month hardcodes

Correctif : datetime.now().year/month comme defaut. Garder params pour historique.

C-19 : tools_state sans resync periodique

Correctif : Resync toutes les 60s, ping chaque outil, mettre a jour state. Independant du watchdog.

C-20 : Path traversal startswith("/")

Correctif : os.path.realpath() + verifier resolved.startswith(allowed_base_dir). 403 si hors repertoire. 5 fonctions.

C-21 : SSH injection face_swapper_model

Correctif : Whitelist modeles connus. shlex.quote() sur TOUS les parametres SSH. Pattern defensif systematique.

C-22 : FAUX POSITIF (nginx IP-restreint malgre absence private:true dans yml)

U-01 : WIN11_HOST hardcode

Correctif : Utiliser DNS Pi-hole win11.internal.nowhere84.com. Env var dans conf.prod.gouroubleu.yml.

U-02 : Race condition pop Redis (= C-10)

Correctif : Couvert par C-10.

U-03 : VRAM estimation max au lieu de sum

Correctif : sum() des VRAM quand multi-modeles sur meme GPU. Prendre en compte modeles deja charges.

U-04 : Upload ecrase fichiers existants

Correctif : Suffixe unique (timestamp/UUID court) ou 409 Conflict si existe. Logger upload.

U-05 : Pas de init.py

Correctif : Ajouter init.py vide dans app/.

U-06 : StrictHostKeyChecking=no sur 2 commandes

Correctif : Ajouter cle host win11 dans known_hosts du container. Retirer StrictHostKeyChecking=no.

U-07 : 13 imports locaux repetes

Correctif : Deplacer imports en haut du fichier.

U-08 : Fooocus seed 2^63 vs ComfyUI 2^32

Correctif : Aligner limites seed par outil. ComfyUI: 2^32-1, Fooocus: 2^63-1.

U-09 : SadTalker job_id sans sanitisation

Correctif : shlex.quote() par principe defensif (meme si UUID interne).

U-10 : Applio 60 parametres positionnels

Correctif : Named arguments ou script wrapper sur win11 qui traduit named → positionnels.

U-11 : Pas de schema.sql ni migrations

Correctif : Exporter schema.sql, dossier migrations/ avec fichiers SQL numerotes, appliquer au demarrage.

U-12 : /health crash si Redis down → boucle restart

Correctif : Catch erreurs dependances dans /health. Retourner 503 degraded, jamais crash.

U-13 : stop_tool("anthropic") SSH inutile

Correctif : Supprimer code mort stop SSH pour Anthropic (service cloud).

U-14 : Batch JSONL result.type pas verifie

Correctif : Verifier result.type, compter succes/echecs, ne pas traiter erreurs comme resultats valides.


Decisions validees — ulias-org (30)

C-01 : Briefing processAnswer logique inversee

Correctif : Inverser la condition (! manquant ou en trop).

C-02 : WS deconnexion session.ws jamais nettoye

Correctif : session.ws = null dans handler close. Verifier ws non null avant send. Cleanup session apres delai.

C-03 : Pipeline runner ne passe pas AbortSignal

Correctif : Passer signal a chaque etape. Verifier signal.aborted avant chaque appel LLM/tool.

C-04 : onDecision callback jamais branche

Correctif : Brancher sur WS. Envoyer question au client, attendre reponse approve/reject. Timeout → auto-reject.

C-05 : CALLBACK_BASE_URL hardcode

Correctif : Env var dans conf.prod.gouroubleu.yml, pas de fallback.

C-06 : CONNECTORS_API_URL fallback port 5400 au lieu de 5403

Correctif : Supprimer fallback. Env var. Utiliser domaine HTTPS avec migration DNS.

C-07 : Cache hash DJB2 32-bit + troncature

Correctif : Remplacer par SHA-256, supprimer troncature.

C-08 : Circuit breaker et cache globaux partages

Correctif : Circuit breaker reste global (logique). Cache isole par session (cle inclut session ID).

C-09 : Prompt overrides globaux

Correctif : Stocker overrides par session, pas en global.

C-10 : Pas de validation ownership (IDOR)

Correctif : Verifier resource.user_id === authenticated_user.id. WHERE id=? AND user_id=? dans SQL.

C-11 : Injection SSH via heredoc ULIAS_EOF

Correctif : Delimiteur dynamique/aleatoire a chaque appel. Valider/limiter commandes par agent.

C-12 : Traduction automatique systematique

Correctif : Configurable par agent/session. Detecter langue, skip si deja langue cible. Cacher langue user.

C-13 : API key en clair dans Supabase

Correctif : Hash SHA-256 (meme pattern que connectors-api C-16). Transversal.

C-14 : editFile ne remplace que premiere occurrence

Correctif : replaceAll() ou regex /g. Option replace_all: boolean (defaut false).

C-15 : message_count increment non-atomique

Correctif : UPDATE SET message_count = message_count + 1 (atomique SQL).

C-16 : GITLAB_TOKEN en clair dans conf.prod

Correctif : Sortir dans fichier secrets non versionne ou variables CI/CD. Regenerer token.

C-17 : /api/agents et /internal/* sans auth

Correctif : Auth API key/JWT sur /api/. API key partagee pour /internal/. Pattern transversal.

U-01 : CLI default port 5510 au lieu de 5515

Correctif : Corriger port. Utiliser domaine HTTPS avec migration DNS.

U-02 : NotificationService code mort

Correctif : Supprimer (notifications via outils connecteur).

U-03 : git-workflow.ts status '??' teste 2 fois

Correctif : Supprimer test duplique.

U-04 : Upload base64 toString('utf-8') corrompt binaires

Correctif : Ecrire buffer directement sans conversion UTF-8.

U-05 : storageGetPublicUrl IP hardcodee

Correctif : Supprimer fallback IP. Env var + DNS.

U-06 : num_ctx ecrase par hardcode 16384

Correctif : Respecter num_ctx passe en parametre. 16384 = defaut si non specifie. Adapter au GPU/modele.

U-07 : consecutiveErrors semantique incorrecte en parallele

Correctif : Fenetre glissante (X erreurs sur Y derniers appels) au lieu de compteur consecutif strict.

U-08 : userId fallback apiKey[:8]

Correctif : Supprimer fallback. Auth doit toujours resoudre un userId. Erreur si pas de userId.

U-09 : forkConversation charge 10000 messages

Correctif : Charger par batches (100). INSERT batch au lieu de N inserts sequentiels.

U-10 : Incoherence instance parameter id vs name

Correctif : Standardiser sur id (UUID). Resoudre nom→id une seule fois.

U-11 : auth.ts hardcode 'Supabase' vs client.ts .id

Correctif : Constante ou env var SUPABASE_INSTANCE_ID utilisee par les deux.

U-12 : dbInsert/dbUpdate retour undefined

Correctif : Verifier retour. Throw si undefined/erreur. Idealement dbInsert/dbUpdate throw eux-memes.

U-13 : Nudge agent injecte message 'user'

Correctif : Role 'system' ou flag is_system. Ne pas persister dans historique visible.


Decisions validees — ulias-org-web (25)

C-01 : setInterval archive polling closure figee

Correctif : Lire valeur courante a chaque tick. Ou pattern reactif Qwik. Cleanup interval.

C-02 : XSS javascript: URI dans Markdown

Correctif : Sanitiser URLs (whitelist http/https/mailto). DOMPurify sur HTML genere.

C-03 : retryObjective window.location.href detruit WS

Correctif : Attendre confirmation envoi WS avant naviguer. Ou update etat local (SPA).

C-04 : Race condition setTimeout(500ms) loadLastConversation

Correctif : Attendre event WS onopen, pas setTimeout.

C-05 : /api/teams fetch sans X-API-Key

Correctif : Ajouter header. Centraliser dans wrapper fetch qui ajoute auth auto.

C-06 : Erreurs reseau silencieuses (catch vides)

Correctif : Supprimer catch vides. Wrapper fetch centralise (toast + log). Gerer erreurs au bon niveau.

C-07 : Etat local desynchronise apres delete/archive echoue

Correctif : Verifier res.ok AVANT de mettre a jour UI. Si echec → erreur, ne pas toucher etat.

C-08 : Suppression sans confirmation

Correctif : Dialogue confirmation avant suppression (confirm() ou modal).

C-09 : Reconnexion WS limitee 5 tentatives

Correctif : Apres 5 rapides → backoff exponentiel (30s, 60s, 120s). Bandeau "connexion perdue" + bouton reconnecter.

C-10 : API key dans chaque message WS

Correctif : Envoyer API key uniquement au premier message (auth). Session WS deja authentifiee.

C-11 : Types TypeScript incomplets events serveur

Correctif : Union type ServerEvent. Typer chaque event.

C-12 : useStore mute dans handler vanilla JS

Correctif : useSignal pour flags simples. Fonction $() pour mutations complexes.

U-01 : searchTimerRef jamais nettoye

Correctif : clearTimeout dans cleanup composant.

U-02 : Modal sans role/aria/focus trap

Correctif : role="dialog", aria-modal="true", focus trap, Escape ferme.

U-03 : Boutons SVG sans aria-label

Correctif : Ajouter aria-label descriptif.

U-04 : div onClick$ sans role/tabIndex

Correctif : Remplacer par <button> natif. Sinon role="button" + tabIndex={0} + onKeyDown$.

U-05 : Pas de live region streaming

Correctif : aria-live="polite" sur zone reponse. aria-busy pendant streaming.

U-06 : 14 types events custom sans typage

Correctif : Enum/union type pour events. Se fait avec C-11.

U-07 : event.data?.title code mort

Correctif : Verifier si vestige → supprimer. Ou corriger mapping.

U-08 : originalMessage absent → retry/edit caches

Correctif : Backend inclure originalMessage. Ou frontend afficher retry/edit sans condition.

U-09 : WS connecte /ws/cli au lieu de /ws/webui

Correctif : Connecter sur /ws/webui.

U-10 : /api/status ne verifie pas API key

Correctif : Backend ajouter auth sur /api/status. Frontend afficher "API key invalide" si 401.

U-11 : revokeObjectURL trop tot

Correctif : Revoquer apres setTimeout(1000ms).

U-12 : setTimeout(500ms) template message

Correctif : Meme fix que C-04 — event au lieu de timer.

U-13 : 9 signaux Qwik par EventCard

Correctif : Regrouper en 1 useStore. Ou calculer a la volee. Attention .sort() dans render.


Decisions validees — dashboard (36)

NOTE : 28 findings sont absorbes par la migration dashboard vers projet GitLab (voir proposition ~/propositions/15-02-2026-13-30-dashboard-projet-gitlab-complet.md). 8 findings sont integres comme exigences du nouveau projet.

Absorbes par la migration (pas de patch sur le vieux code)

C-01, C-02, C-03, C-04, C-05, C-06, C-08, C-09, C-10, C-11, C-12, C-14, C-15, C-16, C-17, C-18, U-01, U-02, U-04, U-06, U-07, U-08, U-10, U-14, U-15, U-16 (faux probleme), U-17, U-18

Exigences pour le nouveau dashboard


Prochaine etape : Implementation

Ordre recommande :

  1. Migration DNS Pi-hole (prerequis pour plusieurs fixes)
  2. connectors-api (22 correctifs — projet le plus critique en securite)
  3. ai-orchestrator (33 correctifs — stabilite GPU + securite)
  4. ulias-org (30 correctifs — IDOR + isolation sessions)
  5. ulias-org-web (25 correctifs — XSS + UX)
  6. Dashboard migration (nouveau projet — depend des fixes 1-5)