Repository navigation
Description
Contexte
Avant la publication de l’application, effectuer une passe dédiée sur le risque des clients customs et des forks open source.
Le client officiel est et doit rester open source. Un fork peut donc modifier l’interface, automatiser des actions ou embarquer un token compromis. Le serveur officiel ne doit jamais faire confiance au binaire utilisé : il doit vérifier l’identité, les droits, l’état du joueur et chaque mutation côté serveur.
Cette issue doit être traitée à la fin de la milestone App, après l’implémentation des flux, afin d’auditer le système réel plutôt qu’une architecture théorique.
Périmètre
Inclus
- Écrire un modèle de menace couvrant les forks custom, l’automatisation, le rejeu de paquets, les tokens copiés ou exposés et les abus de l’économie ;
- Vérifier qu’aucun secret serveur,
client_secret, token permanent ou identifiant sensible n’est embarqué dansApp, les builds mobiles ou les builds desktop ; - Auditer le cycle de vie des tokens Keycloak : durée, rotation, révocation, expiration, issuer, audience et séparation des permissions ;
- Sécuriser l’ouverture WebSocket et vérifier qu’un access token n’est pas exposé dans les URL ou les logs ;
- Valider les paquets entrants à la frontière RestWs : allowlist, schémas runtime, tailles maximales, types, valeurs autorisées et champs inattendus ;
- Ajouter ou vérifier les limites par compte, IP et connexion : fréquence, taille des messages, actions simultanées et comportement abusif ;
- Vérifier la protection contre le rejeu et la double exécution des actions à effet de bord ;
- Vérifier que Core recalcule et contrôle toujours les coûts, récompenses, délais, propriétaires, collecteurs, inventaires, cibles et permissions ;
- Supprimer ou masquer les tokens et données sensibles dans les logs de production ;
- Tester le serveur avec des paquets fabriqués à la main et un client minimal non issu du code de l’application ;
- Documenter la politique des clients alternatifs, des forks, de la marque Crownicles et des obligations AGPL ;
- Vérifier que les protections retenues restent compatibles avec F-Droid, les builds communautaires et les clients macOS/Linux/Windows.
Canaris de protocole et signaux d’abus
Mettre en place des signaux de détection faciles à observer dans les logs, mais sans transformer le protocole en mécanisme de sécurité par obscurité :
- journaliser de façon structurée les paquets inconnus, les champs inattendus, les enums impossibles, les index invalides, les identifiants de requête rejoués et les actions incompatibles avec l’état du joueur ;
- détecter les séquences impossibles, les cadences anormales, les rafales de requêtes et les réponses systématiquement trop rapides pour le parcours normal ;
- ajouter si nécessaire un handshake ou une négociation de version/capacités explicite, avec un signal lorsqu’un client contourne ou falsifie le contrat public ;
- envisager des canaris purement observables et sans effet de jeu, par exemple des paquets ou capacités non documentés qui doivent être rejetés et journalisés, sans fausse récompense, faux coût, perte de ressource ou piège pouvant affecter un joueur ;
- produire un événement de sécurité exploitable par le monitoring avec le compte, la connexion, le type de signal, la version du protocole et le contexte minimal nécessaire, sans token ni secret dans les données ;
- conserver les signaux avec une durée de rétention et un accès documentés, en évitant de journaliser inutilement des données personnelles ;
- ne jamais bannir sur un seul signal : combiner plusieurs signaux indépendants avec l’impact observé, prévoir les faux positifs des anciennes versions, des forks légitimes, de l’accessibilité et des problèmes réseau, puis appliquer une restriction temporaire ou une revue manuelle avant un bannissement définitif ;
- tester ces canaris avec l’app officielle, un client minimal conforme, un client volontairement malformé et un scénario d’automatisation afin de mesurer le bruit et la valeur réelle de chaque signal.
Ces canaris ne pourront pas identifier un client custom qui reproduit parfaitement le protocole public. Leur but est de faire remonter rapidement les clients mal écrits ou abusifs, pas de prouver quel binaire est officiel.
Hors périmètre
- Empêcher techniquement tous les forks ou tous les clients customs ;
- Ajouter une clé secrète dans l’application, de l’obfuscation ou une détection basée uniquement sur le User-Agent ;
- Rendre obligatoire App Attest, Play Integrity ou une autre preuve du binaire officiel ;
- Réécrire le protocole ou déplacer les règles de jeu dans l’application ;
- Introduire des pièges cachés qui modifient l’économie, faussent l’interface, consomment une ressource ou peuvent bannir un joueur sans preuve indépendante ;
- Traiter les règles propres à Apple, F-Droid ou Steam déjà couvertes par leurs issues de publication, sauf pour vérifier leur compatibilité avec cet audit.
Terminé quand
- Le modèle de menace, les risques acceptés et les protections retenues sont documentés ;
- Un client custom peut se connecter uniquement avec un compte valide et ne peut agir qu’au nom de ce compte ;
- Un paquet forgé ne peut pas modifier un prix, une récompense, une durée, une propriété ou une permission validée par Core ;
- Un token copié peut être révoqué et n’apparaît ni dans les logs ni dans les URL de production ;
- Les paquets invalides, trop volumineux, trop fréquents ou rejoués sont rejetés sans crash ni effet de bord ;
- Les canaris de protocole sont non destructifs, documentés, testés et envoyés vers un événement de monitoring structuré ;
- Chaque signal possède un niveau de confiance, une procédure de corrélation et une stratégie de faux positifs ;
- Aucun bannissement automatique définitif ne repose sur un seul signal ;
- Les limites d’abus et la procédure de sanction ou de révocation sont définies ;
- Les tests couvrent au minimum l’usurpation de joueur, le rejeu, la double dépense, la double récompense, le spam, les paquets malformés et les faux positifs d’un client conforme ;
- La documentation explique clairement ce qui est autorisé pour les forks et ce qui constitue un abus sur le serveur officiel ;
- L’audit ne bloque pas les builds F-Droid, les clients desktop ou les forks open source légitimes ;
- Les contrôles de sécurité et les tests ciblés passent dans les services concernés.
Activity
BastLast commentedon Aug 20, 2026
Décision concernant les anciennes versions et les clients customs
Le serveur officiel ne doit pas faire confiance au binaire utilisé, mais il doit pouvoir refuser les clients devenus incompatibles. Le contrôle de version sera placé dans
RestWs, après authentification Keycloak et avant tout envoi MQTT versCore.Le client devra déclarer au handshake ou à l’ouverture WebSocket : plateforme, version native, numéro de build,
runtimeVersionet version de protocole. RestWs comparera ces informations à une politique configurable : version minimale supportée, build minimal, runtime accepté, date d’effet et liens vers les stores.Une ancienne version recevra une réponse explicite
APP_UPDATE_REQUIRED, sans paquet de jeu et sans accès à Core. Ce mécanisme n’est pas une preuve qu’un binaire officiel est utilisé : un fork peut reproduire le protocole. La sécurité réelle reste l’authentification, la validation des paquets, les limites d’abus et les règles recalculées par Core.Contraintes à auditer
La publication à une date choisie par Apple ou Google ne garantit pas l’installation simultanée de tous les utilisateurs. Le serveur doit donc accepter une transition entre plusieurs versions compatibles et ne bloquer qu’à la date d’effet explicitement configurée.
keep mobile sessions across dev restarts Relates to #4791
drop the password grant and its unused routes; Relates to #4791
harden the realm and document its settings; Relates to #4791
BastLast commentedon Sep 22, 2026
Une partie du périmètre « cycle de vie des jetons Keycloak » a été traitée le 22/09, à reprendre telle quelle lors de l'audit final plutôt qu'à refaire.
Plus aucun client n'accepte le grant mot de passe. Il était actif sur
crownicles-app— le client public de l'app — ainsi que suradmin-cli,discordetrestWs. N'importe qui pouvait donc éprouver des mots de passe par appel direct au point de terminaison, sans jamais voir le formulaire. Les deux routes qui l'utilisaient (POST /login,POST /refreshToken) n'étaient appelées par personne : l'app parle à Keycloak en PKCE, y compris pour le rafraîchissement. Elles sont supprimées, avecKeycloakUtils.loginUser,refreshUserTokenetcheckUserAccessToken. L'Admin API continue de fonctionner : elle utilisait déjàclient_credentials.keycloak/realm.jsonindiquait déjàdirectAccessGrantsEnabled: falsepourcrownicles-app, alors que le realm réel était àtrue. Un ré-import depuis un export ramène ces valeurs. Vérifier le realm en fonctionnement, pas le fichier versionné.Autres points fermés
crownicles-appn'accepte pluscrownicles://*maiscrownicles://auth*: un schéma personnalisé n'est pas exclusif, une autre application peut l'enregistrer et intercepter le code. (non testé sur appareil)passwordPolicyétait vide : un mot de passe d'un caractère passait. Désormais 10 caractères minimum, refus du nom d'utilisateur et de l'adresse.failureFactor30 → 10.26.7.4au lieu delatest.Restant sur ce périmètre : modèle de menace, validation des paquets à la frontière RestWs, limites par compte, exposition du jeton à l'ouverture WebSocket.
BastLast commentedon Sep 22, 2026
Réserve levée : le resserrage de
crownicles-app.redirectUris(crownicles://*→crownicles://auth*,exp://*/--/auth*,http://localhost:8081/auth*) a été testé sur iPhone — la connexion Discord aboutit et le retour d'authentification est reçu normalement.Ce point du périmètre est donc clos et vérifié sur appareil, plus seulement sur le papier.