Import initial de la documentation : statut, roadmap, plans V1/V2, specs verticales (creche, sport), audits securite, plan de test, analyse concurrentielle et maquettes de design. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7.4 KiB
7.4 KiB
Audit manager-service — incohérences & pistes d'amélioration
Audit du 2026-07-13/14. Trois axes analysés : Controllers/Security, Services/Data, DTOs/Config/Tests.
Déjà corrigé (2026-07-14)
- Clé API sur-privilégiée —
ApiKeyAuthenticationHandlerne donne plus le claimContentEditoraux clés API (visiteurs). Seul le JWT peut écrire du contenu. - IDOR
UserController—GetDetail/UpdateUser/DeleteUserfiltrent maintenant parInstanceIddu claim (sauf SuperAdmin) ;CreateUserforce l'instanceIdde l'appelant ; garde-fou de rôle sur update/delete (impossible d'agir sur un rôle supérieur). - IDOR
DeviceController—Getfiltre par instance,GetDetail/Createne sont plusAllowAnonymous,Update/UpdateMainInfos/Deletevérifient l'appartenance à l'instance, changement d'instance interdit pour un non-SuperAdmin. NRE potentielle surapplicationInstancecorrigée. - IDOR
AiController/StatsController—instanceId(query/body) comparé au claim de l'appelant (sauf SuperAdmin) avant tout traitement (évite la consommation du quota IA ou la lecture de stats d'une autre instance).
Non traité volontairement : ConfigurationController (lecture par instanceId via policy AppReadAccess) — probablement voulu car c'est du contenu public affiché aux visiteurs (musée), pas une donnée sensible. À confirmer avant de restreindre.
Critique — non traité, priorité suivante
- Secrets committés en clair dans Git : JWT signing key,
SecuritySettings.Secret, clés API OpenWeather/Gemini, connection strings Postgres/Mongo prod, mot de passe MQTT, token bot Telegram (appsettings*.json,Deployment/.env), pepper scrypt en dur (ProfileLogic.cs). Le dossierRELEASE/republie d'anciens secrets. Seulfirebase-adminsdk.jsonest correctement ignoré. → Rotation de tous les secrets, passage en variables d'environnement/secrets Docker, purge de l'historique Git (git filter-repo), suppression deRELEASE/.
Haute
Startup.cs:EnableSensitiveDataLogging()+LogTo(Console, Information)actifs en permanence (toutes valeurs SQL loggées en prod) → conditionner àIsDevelopment().- Services Mongo legacy (
SectionDatabaseService,Instance/Configuration/Device/Resource/UserDatabaseService) :new MongoClient(...)dans le constructeur en scopeAddScoped→ un pool de connexions par requête. À passer en singleton. Couche 100% synchrone/bloquante. MyInfoMateDbContext: conversions JSONB (List<TranslationDTO>) sansValueComparer→ une mutation in-place (ex.AgendaSyncService.SetTranslation) n'est pas détectée par EF ni persistée.AssistantService.cs:new HttpClient()manuel en boucle (risque d'épuisement de sockets) au lieu d'IHttpClientFactory; duplication de la logique de fetch d'agenda déjà présente dansAgendaSyncService; N+1 surResources.
Moyenne
- JWT :
RequireExpirationTime = falsealors queValidateLifetime = true(tokens sansexpacceptés, non révocables) ;ValidateIssuer/ValidateAudience = falsealors que configurés (config morte). - Clés API stockées en clair en plus du hash (
ApiKeyAuthenticationHandler.cs:40, comparaison non constant-time). - Bootstrap de clé API par pincode en
AllowAnonymoussans rate limiting (InstanceController.GetAppKeyByPin/GetInstanceByPinCode) → brute-forçable. - Exceptions internes exposées dans les réponses (
ex.Messageen 500,AuthenticationControllersérialise l'objet exception entier) → middleware d'erreur global à généraliser. - Backdoor
#if DEBUGdansAuthenticationController.Login— retirer ou conditionner explicitement. - Package
Microsoft.AspNetCore.Authentication.JwtBearerv2.1.30 (ère .NET Core 2.1) sur une app .NET 8. - Double
SaveChangesAsyncdans l'audit (MyInfoMateDbContext.cs:67-74) — 2e save no-op,resultgonflé. → À revérifier : un bug voisin a été corrigé le 2026-08-06 —BuildAuditEntries()ajoutait unAuditLogau contexte pendant l'énumération duChangeTracker, ce qui levaitInvalidOperationException: Collection was modifiedsur toute écriture d'entité auditée (Section, Resource, Configuration, Device, User, Instance). Invisible jusque-là parce que la suite de tests ne compilait plus. Vérifier si ce point est devenu caduc. SectionFactory: ~700 lignes de mappings dupliqués (extraireMapBase),dto.dateCreation.Value/.order.Valuesans garde (InvalidOperationException), double (dé)sérialisation System.Text.Json → Newtonsoft.RemoteEventAgendaDTO.ParseDate: fallbackDateTime.TryParsesansInvariantCulture(ambiguïté JJ/MM selon locale serveur) ;date_hourjamais recombiné à la date ;FalseToNullConvertercasse si l'API PHP renvoie[]au lieu defalse. Zéro test sur ce code, pourtant le plus risqué du repo (parsing JSON externe non maîtrisé).AppSettingsProvider: état statique mutable alimenté depuis le constructeur deStartup, non thread-safe → passer àIOptions<T>.- Tests : provider EF InMemory alors que le projet dépend de NetTopologySuite + JSONB → les requêtes spatiales/traductions Npgsql ne sont jamais réellement validées.
- Duplication massive du pattern try/catch dans les controllers (candidat à un filtre d'exception global).
- Absence quasi générale d'
AsNoTracking()en lecture ; pas deCancellationTokensur les jobs Hangfire. IHexIdGeneratorServicejamais enregistré en DI →new HexIdGeneratorService()instancié partout ;System.Randomnon thread-safe/non crypto pour la génération d'IDs (collisions possibles).
Basse
- Conventions REST hétérogènes : id dans le body au lieu de la route (
PUT/DELETE),DELETErenvoyant202+string au lieu de204, mélangeObjectResult/IActionResult,SaveChanges()sync dans des méthodesasync. PasswordUtils:System.Randomstatique partagé pour générer codes/pincodes (prévisibles), MD5 obsolète,RNGCryptoServiceProvider/MD5CryptoServiceProviderdépréciés.- Code mort :
ExternalService(MqttClientService jamais utilisé, sous-système MQTT commenté dans Startup), policy CORSAllowAlldéfinie mais jamais appliquée,LanguageInitstatique mais injecté en DI. ImageHelper.ResizeImageretournedynamic, objets GDI (Graphics/Bitmap/Font) non disposés, fragile sur Linux (System.Drawing.Common). → Confirmé le 2026-08-07 : c'est du code mort. Le seul appelant estResourceController.Upload, l'endpoint legacy base64 que manager-app n'utilise plus depuis la bascule Firebase. EtSystem.Drawing.Commonne fonctionne pas sur Linux depuis .NET 6 sans libgdiplus — l'image finale étantaspnet:8.0Linux, ce code lèverait une exception s'il était appelé. À supprimer ; le redimensionnement passe côté client (v2/media-storage-plan.md).- CORS : domaines autorisés codés en dur dans
Configureau lieu de venir de la config. - Ordre middleware :
UseCorsplacé aprèsUseAuthentication/UseAuthorization— ordre recommandé : Routing → CORS → Authentication → Authorization.
Notes complémentaires
WeatherSyncService.cs: catch qui écrit surConsole.WriteLineau lieu d'ILogger.AgendaSyncService.cs: double ajout redondant (section.EventAgendas.Add+db.EventAgendas.Add) ; incohérence de pattern de scope Hangfire entreAgendaSyncServiceetWeatherSyncService.SectionFactory.ToDTO: sentinelleStartDate?.Year > 1000pour détecter une date "nulle" — fragile.