17 audit site 2026 07 14 - LaurentSta/Oneduc GitHub Wiki
17 — Audit site du 14 juillet 2026
Public : développeurs.
Contexte
Suite à l'audit du 5 juillet 2026, qui avait relevé 8 points à corriger. Cette fiche vérifie l'état de chacun de ces points, corrige ceux qui restaient ouverts, et refait un crawl/validation complet de l'application.
Périmètre consulté
Audit réalisé depuis /var/www/Oneduc_Dev, en environnement local, avec le serveur Laravel lancé sur http://127.0.0.1:8010.
| Axe | Couverture |
|---|---|
| Suivi de l'audit précédent | Vérification une à une des 8 lignes de 14-audit-site-2026-07-05.md dans le code actuel |
| Routes | php artisan route:list --json |
| Pages publiques | Crawl HTTP des 23 routes GET publiques sans paramètres |
| Validation | php artisan test, npm run build, php artisan migrate:status, php artisan about |
Suivi des 8 points de l'audit du 5 juillet
| Priorité | Point | État constaté le 14/07 | Action |
|---|---|---|---|
| Haute | /inscription en erreur 500 |
Déjà corrigé le 05/07 (redirection 301 vers /inscription-formateur) |
Aucune — vérifié par crawl |
| Haute | Test ModuleBuilder rouge | Déjà corrigé le 05/07 (test aligné sur le contrat media_id/url) |
Aucune — vérifié par php artisan test |
| Haute | Connexion stagiaire par code sans throttling | Déjà corrigé le 05/07 (rate limiter connexion-code, 10/min/IP) |
Aucune — vérifié dans AppServiceProvider |
| Haute | Accès module trop large (Module::isVisibleTo()) |
Partiellement corrigé le 05/07 : la méthode existait mais deux points d'accès ne l'appelaient pas encore. Frontend\LectureController avait été corrigé entre-temps (8/07), StagiaireController::StagiaireModuleDetail() restait ouvert |
Corrigé aujourd'hui — voir ci-dessous |
| Haute | SCORM legacy écrit last_session_time absent de scorm_scores |
Déjà corrigé le 05/07 (colonne ajoutée par migration) | Aucune — vérifié par migrate:status |
| Moyenne | LessonFeedbackController::store() redirige vers route inexistante |
Déjà corrigé le 05/07 | Aucune |
| Moyenne | FormRequests authorize() = false (StoreModuleRequest, StoreGroupeRequest) |
Toujours ouvert | Corrigé aujourd'hui — voir ci-dessous |
| Basse | Import mort ScormInteractionController |
Déjà corrigé le 05/07 (retiré avec le correctif S7), mais resté coché comme "à faire" dans la roadmap par oubli de mise à jour de la doc | Doc mise à jour, aucun changement de code nécessaire |
Sur les 8 points d'origine, 6 étaient déjà résolus. Les 2 restants ont été corrigés dans le cadre de cet audit.
Correctifs appliqués aujourd'hui
1. Faille de sécurité — accès au détail d'un module hors groupe (Haute)
StagiaireController::StagiaireModuleDetail() (route stagiaire.module.detail) chargeait le module avec Module::active()->findOrFail($id) sans jamais vérifier que le stagiaire authentifié appartenait à un groupe auquel ce module est affecté. Un stagiaire pouvait donc consulter le détail, la progression et les objectifs pédagogiques de n'importe quel module actif du site en devinant/énumérant son identifiant dans l'URL — la même classe de faille que celle déjà corrigée sur Frontend\LectureController le 8 juillet.
Correctif : ajout de abort_unless($module->isVisibleTo($user), 403); juste après le chargement du module, dans app/Http/Controllers/StagiaireController.php.
Test ajouté dans tests/Feature/ModuleVisibilityTest.php :
a stagiaire with no group assignment cannot open the module detail page of an active module→ attend un 403a stagiaire in a group with the module assigned can open the module detail page→ attend un 200 (non-régression)
2. FormRequests inutilisables (Moyenne)
StoreModuleRequest::authorize() et StoreGroupeRequest::authorize() retournaient false, ce qui les rend inutilisables (403 systématique) si elles étaient un jour injectées dans un contrôleur — elles ne sont actuellement utilisées nulle part dans le code (StoreModule et GroupeController valident encore en ligne).
Correctif : les deux méthodes retournent désormais true, ce qui aligne ces classes sur la convention déjà en place dans le reste du projet (ContactRequest, LoginRequest, ScormImportRequest) — l'autorisation réelle est du ressort du middleware de route (auth, role:formateur, association.member), pas du FormRequest.
Fichiers modifiés : app/Http/Requests/StoreModuleRequest.php, app/Http/Requests/StoreGroupeRequest.php.
État des routes
php artisan route:list --json retourne 513 routes (411 lors de l'audit du 5 juillet — croissance normale, une dizaine de fonctionnalités livrées depuis : émargement, consommation IA, outils buzzer/vrai-faux/pendu/mémoire, génération IA, etc.).
| Espace | Nombre de routes |
|---|---|
/formateur |
208 |
/admin |
135 |
/stagiaire |
53 |
/observateur |
9 |
| Routes publiques, auth partagée, SCORM et outils live | 108 |
Crawl HTTP public
23 routes GET publiques sans paramètres testées (même méthodologie que le 5 juillet).
| Statut | Nombre | Détail |
|---|---|---|
| HTTP 200 | 22 | Accueil, catalogue, pages légales, connexion, inscription formateur, contact, nuage de mots public, accès stagiaire, etc. |
| HTTP 301 | 1 | /inscription → redirection volontaire vers /inscription-formateur |
0 erreur HTTP 500. Le crawl public est entièrement sain.
Validations techniques
| Commande | Résultat |
|---|---|
php artisan test |
268 tests passés, 0 échec (1295 assertions) |
npm run build |
Réussi, mêmes avertissements Vite qu'au 5 juillet (chunks > 500 kB, directives "use client") — pas de régression |
php artisan migrate:status |
Toutes les migrations marquées Ran, aucune en attente |
php artisan about --only=environment,cache,drivers |
Laravel 11.42.0, PHP 8.3.6, DB MySQL, queue/session/cache database |
Points à corriger restants (hors périmètre de cet audit)
Ces points n'étaient pas dans la liste du 5 juillet et restent en dette technique, sans impact de sécurité immédiat :
| Priorité | Point | Localisation |
|---|---|---|
| Moyenne | attempts_count SCORM jamais incrémenté |
SCORMController.php |
| Haute (analytics) | scorm_interactions non alimenté pour les leçons |
SCORMController::saveProgress() |
| Moyenne | Group sans SoftDeletes |
app/Models/Group.php |
| Haute (fonctionnel) | Stagiaire multi-groupe — .first() uniquement dans StagiaireModules() |
StagiaireController.php |
| Maintenance | ModuleController (1185 lignes), StagiaireController (794 lignes) |
Backend/ModuleController.php, StagiaireController.php |
Ces éléments sont documentés en détail dans 11-roadmap.md.