OBS-001. logging_config.py configurait un fichier auth.log avec rotation,
un logger nomme 'team_tryouts.auth' et un filtre de redaction. Mais
get_auth_logger n'etait importe nulle part : le fichier etait cree et
restait vide. Aucune connexion, aucun echec, aucun verrouillage, aucun
changement de role, aucune suppression de compte ne laissait de trace.
En cas de suspicion de compromission, il n'y avait rien a consulter.
Ajout de log_auth_event(event, **fields), qui emet des paires cle=valeur
ordonnees -- greppable sans dependance de journalisation JSON.
Evenements couverts
authentification login.success, login.failure,
login.failure.unknown_user, login.rejected.locked,
login.rejected.deactivated, account.locked, logout,
account.registered
administration account.created_by_admin, account.updated,
account.role_changed (avec ancien et nouveau role),
account.deleted, account.password_reset_by_admin
libre-service account.password_changed
Le champ ip vient de request.remote_addr, donc de X-Forwarded-For. Tant que
Waitress tourne avec trusted_proxy='*' (SEC-WEB-002), cette valeur est
choisie par l'appelant : c'est une indication, pas une preuve. Le point est
documente dans la docstring.
Un test a fait remonter ARCH-003, jusqu'ici classe comme fragilite latente
Journaliser en fin de edit_user levait DetachedInstanceError : le
changement de role appelle db.session.remove() en plein cycle de requete,
ce qui detache current_user de la session. Le code s'en tirait parce qu'il
redirigeait immediatement sans plus y toucher. L'identite de l'acteur est
desormais capturee en debut de traitement. Le constat est donc confirme
comme reel, et non plus seulement probable -- sa correction de fond reste
au programme.
15 tests, dont 4 sur le filtre de redaction lui-meme : c'est un controle de
securite, il doit etre verifie.
Co-Authored-By: Claude Opus 5 <[email protected]>
/health divulguait le message brut du pilote
L'endpoint n'est pas authentifie et renvoyait f'error: {str(e)}'. Les
exceptions psycopg contiennent regulierement l'hote, le port, le nom de
la base et l'utilisateur. Le detail part desormais dans les journaux,
la reponse ne porte plus qu'un statut.
Filtre nl2br non echappant
Markup('<br>'.join(...)) marquait le texte comme sur sans l'echapper.
Le filtre n'etant utilise dans aucun gabarit, la faille etait latente :
elle se serait ouverte au premier usage. Corrige en Markup('<br>').join(),
qui echappe chaque segment. Verifie : nl2br('<script>alert(1)</script>')
rend desormais <script>alert(1)</script>.
Filtre de redaction des secrets sans effet
SensitiveDataFilter n'inspectait que record.msg. Or le code journalise
en style parametre ('...: %s', valeur) : record.msg ne contient que la
chaine de format, et la donnee sensible vit dans record.args, ignore.
La redaction ne s'appliquait donc pratiquement jamais. Le record est
desormais rendu avant filtrage, puis args vide.
Sortie console conditionnee a FLASK_DEBUG
En production, l'application n'ecrivait rien sur stdout, precisement ou
regarde la console Pterodactyl. Le handler devient inconditionnel, seul
son niveau varie.
Journaux du bot Discord perdus
discord_bot.py utilise getLogger(__name__), soit 'app.discord_bot'.
Aucun handler n'etait attache a la hierarchie 'app' : les INFO etaient
jetes et les WARNING+ tombaient sur le handler de dernier recours, sans
format. Les handlers sont desormais rattaches au logger de paquet.
X-XSS-Protection retire (app.py et nginx.conf)
En-tete deprecie, l'auditeur vise a ete supprime des navigateurs
courants et ses dernieres implementations introduisaient elles-memes
des vulnerabilites.
Co-Authored-By: Claude Opus 5 <[email protected]>