From 6653a7419dc1274c04ff5f62ff952de0d08d67da Mon Sep 17 00:00:00 2001 From: Corentin JOGUET Date: Tue, 16 Jun 2026 14:19:48 +0200 Subject: [PATCH] docs(journal): audit reel des livrables P2/P3 (2026-06-16) (#22) --- .../2026-06-16--audit-reel-livrables-p2-p3.md | 187 ++++++++++++++++++ docs/journal/README.md | 1 + 2 files changed, 188 insertions(+) create mode 100644 docs/journal/2026-06-16--audit-reel-livrables-p2-p3.md diff --git a/docs/journal/2026-06-16--audit-reel-livrables-p2-p3.md b/docs/journal/2026-06-16--audit-reel-livrables-p2-p3.md new file mode 100644 index 0000000..67dfac2 --- /dev/null +++ b/docs/journal/2026-06-16--audit-reel-livrables-p2-p3.md @@ -0,0 +1,187 @@ +# Audit reel des livrables P2/P3 — verification sur pieces + +**Date** : 2026-06-16 +**Branche** : `docs/journal-audit-2026-06-16` -> `dev` +**PR** : cette note (PR dediee) ; remediations associees : #19, #20, #21 +**Auteur** : BYAN +**Duree estimee** : 1 session + +--- + +## Ce qui a ete fait + +Verification du travail livre le 2026-06-15 (8 PR : P2 auth/RBAC/PIN, P3 shell + +CRUD categories/produits + set-PIN + throttle PIN), a la demande explicite de +controler "le reel, pas le journal" — suspicion d'un ecart non documente. + +Methode : controle sur pieces uniquement. + +- git : timeline du 2026-06-15, parents de commit, branches reellement presentes + cote Forgejo (2 : `dev`, `main`) ; +- code lu a la ligne (`file:line`) ; +- base MariaDB live interrogee (schema, seed, migrations trackees) ; +- suite de tests rejouee en conteneur ; API CI Forgejo (264 runs analyses) ; +- sweep multi-agents : 10 dimensions (PR #11-#18 + regles SbD RG-T01..T22 + + infra/config), chaque finding re-verifie en adversarial (confirmer le miss ou + le refuter), plus un critique de completude. + +--- + +## Resultat — le socle metier tient + +Confirme enforced dans le code (pas seulement documente), `file:line` a l'appui : +RG-T01 (CSRF sur les mutations), T02 (garde de session + re-verif `is_active`), +T03 (autorisation par permission, pas par nom de role), T06 (requetes preparees), +T08 (mutation + `audit_log` dans une seule transaction), T13 (PIN d'action +sensible), T14 (audit append-only), T16 (allowlist de colonnes), T18 (validation +serveur bornee), T22 (throttle PIN isole du login). + +Base live conforme au seed documente (5 roles / 23 permissions / 57 lignes de +matrice / 14 allergenes / 9 categories / 53 produits / 13 menus) ; migrations +`0001` + `0002` trackees appliquees. 188 tests / PHPStan L6 : reproduits verts en +conteneur. + +--- + +## Miss confirmes (par gravite) + +Severite issue de la passe adversariale, qui a parfois revu a la baisse +l'evaluation initiale. + +### CRITIQUE — durcissement php.ini absent du conteneur en service [OUVERT] + +`docker/php-fpm/php.ini` (durci le 2026-06-15 : `allow_url_fopen=Off`, +`disable_functions`, `cgi.fix_pathinfo=0`, `enable_dl=Off`) n'est pas actif sur +`wakdo-app`. `docker exec wakdo-app php -i` renvoie `allow_url_fopen=On`, +`disable_functions` vide, `enable_dl=On`. Cause : l'image date du 2026-04-30 (le +`php.ini` est `COPY`-e a la build, pas monte) et n'a pas ete reconstruite depuis +le durcissement. Correctif : rebuild de `wakdo-app` puis re-verif via `php -i`. + +### HIGH — la CI n'executait aucun test d'integration DB [CORRIGE, PR #21] + +`static-tests` lancait `phpunit` sans base ni `WAKDO_DB_TESTS=1` : les 7 +`tests/Integration/*DbTest` s'auto-skippaient (13 skips), donc le SQL porteur de +securite (upsert atomique du throttle, predicat `AND r.is_active = 1`, audit +in-transaction, FK RESTRICT/CASCADE) n'etait valide par aucun test en pipeline. +Le double `FakeDatabase` n'execute pas le SQL : une regression de ces requetes +passait la CI au vert. Corrige par un service MariaDB ephemere + application +schema/seed + `WAKDO_DB_TESTS=1` + `--fail-on-skipped`. CI verte verifiee sur le +runner (run #78 push + run #79 PR #21 : `secret-scan` / `php-lint` / +`static-tests` au vert). + +### MEDIUM + +- XSS stockee latente dans la borne (RG-T15) : 3 scripts injectaient + `product.nom` / `item.libelle` / `product.image` dans `innerHTML` sans + echappement (seul `page-product-menu.js` etait conforme). Donnees statiques + aujourd'hui, mais `data.js` documente la bascule P4 vers `/api/products` + (valeurs CRUD admin). [CORRIGE, PR #20] +- Liens de nav admin morts : `/admin/menus|orders|users|roles` exposes dans le + layout (conditionnes par permission) sans route -> 404 JSON. [OUVERT] +- Utilisateur DB applicatif en `GRANT ALL PRIVILEGES` alors que la doc + (compose, `backup-db.sh`) decrit un moindre privilege (SELECT / LOCK TABLES / + SHOW VIEW). [OUVERT] +- Retention RGPD (audit / order) + purge throttle : documentees comme purges + cron mais non implementees (pas de job actif, pas de script, vars non + injectees au conteneur cron). [OUVERT] + +### LOW + +- Enumeration d'email sur le reset de mot de passe : reponse instantanee sur + email inconnu vs travail + ecriture sur email connu. La parite timing/ecritures + tient sur le login, pas sur le reset. +- Suppression produit non entierement FK-safe : `product_ingredient.product_id` + est `ON DELETE CASCADE` (omis du docblock) -> suppression silencieuse de + recette possible, sans trace dans l'audit. Latent : table vide au seed actuel. +- Page `/admin/profile/pin` non liee dans la nav (joignable par URL directe). +- `PASSWORD_ALGO` expose en env mais code en dur (`PASSWORD_ARGON2ID`) : un + changement de valeur serait sans effet. +- Chemin d'echec PIN non atomique (`logFailedPin` hors transaction puis + `recordFailure` dans sa propre transaction), en tension avec RG-T08 (qui tient + sur le chemin de succes). +- `borne/data/produits.json` (66 produits, maquette statique) diverge de la + table `product` (53). + +### Faux positifs ecartes par la passe adversariale + +- "Throttle login partiel / non teste" : la double porte compte + IP est + complete, l'increment atomique et le predicat de fenetre sont couverts (unit + + integration), l'IP du dernier hop `X-Forwarded-For` n'est pas falsifiable. +- "Code mort `userId === null` post-guard" : c'est le narrowing `?int -> int` + requis par PHPStan L6, pas un defaut. + +--- + +## Remediations livrees cette session + +- **PR #19** : suppression des 6 maquettes `.html` du back-office servies sans + authentification (exposition / information disclosure). +- **PR #20** : echappement (`escHtml` centralise dans `state.js`) des chaines + data-derived injectees en `innerHTML` dans les 3 scripts kiosk (RG-T15). +- **PR #21** : execution des tests d'integration DB en CI (service MariaDB + + `WAKDO_DB_TESTS=1` + `--fail-on-skipped`). Recette validee en local (188 tests + / 525 assertions / 0 skip) puis sur le runner. + +--- + +## Reste a traiter (ordre suggere) + +1. **CRITIQUE** : reconstruire l'image `wakdo-app` pour activer le `php.ini` + durci. +2. **MEDIUM** : retirer ou router les liens de nav morts ; appliquer un GRANT de + moindre privilege au user DB ; implementer la purge RGPD / throttle (job cron + + script). +3. **LOW** : decoy de timing sur le reset ; pre-check FK + trace audit a la + suppression produit ; lien de nav vers la page PIN ; honorer ou retirer + `PASSWORD_ALGO` ; atomiser le chemin d'echec PIN. + +--- + +## Criteres RNCP couverts + +- **Bloc 5 - Cr 7.d.2 / 7.d.3** (CI/CD : application testee avant deploiement, + integration continue testee) : PR #21 fait reellement tourner les tests + d'integration en pipeline (avant, ils etaient skippes). +- **Bloc 2 - Cr 4.f.2** (maitrise de l'outil collaboratif : Git, PR, branches, + hooks) : remediation via PR dediees et branches courtes, CI gardee. +- **Securite (transverse)** : verification que les regles SbD documentees sont + effectivement appliquees ; fermeture d'une exposition (maquettes non gardees) + et d'une XSS latente. + +--- + +## Questions anticipees du jury + +- **Q** : "Vos tests etaient verts ; comment un trou a-t-il pu subsister ?" + **R** : la suite unitaire (188 verts) ne touchait pas le SQL reel (double en + memoire), et les tests d'integration s'auto-skippaient en CI. Le badge vert ne + couvrait pas la couche SQL. Corrige (PR #21) et garde par `--fail-on-skipped`. +- **Q** : "Le graphe des branches semble casse." + **R** : workflow squash-merge -> historique `dev` lineaire (1 PR = 1 commit) ; + les branches de feature apparaissent en moignons car le squash ne cree pas le + 2e parent d'un merge classique. Choix assume. +- **Q** : "Pourquoi le durcissement php.ini n'etait-il pas actif ?" + **R** : le `php.ini` est `COPY`-e dans l'image, pas monte ; l'image n'avait pas + ete reconstruite depuis le durcissement. Detecte par `php -i` sur le conteneur, + corrige par un rebuild. + +--- + +## Points d'amelioration conscients + +- Les findings MEDIUM / LOW restants sont traces ici et priorises ; ils ne + bloquent pas la suite P3, mais sont a fermer avant une mise en avant securite + au jury. +- `--fail-on-skipped` est volontairement strict : tout futur test legitimement + skippe devra etre justifie explicitement. + +--- + +## Liens vers artefacts + +- PR : #19 (maquettes), #20 (escHtml RG-T15), #21 (tests DB en CI). +- Fichiers cles : `.forgejo/workflows/ci.yml`, `docker/php-fpm/php.ini`, + `src/public/borne/assets/js/{state,page-products,page-product,page-cart}.js`, + `src/app/Auth/*`, `src/app/Controllers/*`, `db/migrations/`, `db/seeds/`. +- Methode : sweep multi-agents (10 dimensions) + verifications adversariales, + pilote depuis Claude Code. diff --git a/docs/journal/README.md b/docs/journal/README.md index 2b7afa7..73947df 100644 --- a/docs/journal/README.md +++ b/docs/journal/README.md @@ -32,6 +32,7 @@ Les fichiers sont ordonnes chronologiquement par leur nom. | 2026-04-30 | [smoke-test-infra](2026-04-30--smoke-test-infra.md) | Smoke test bout-en-bout sur serveur reel : fusion .env, switch FQDN sur stark.a3n.fr, subnet explicite RFC 1918, fix init cron + healthz | `feat/infra-docker` | | 2026-06-04 | [conception-prodlike-revision](2026-06-04--conception-prodlike-revision.md) | Revue d'alignement P1 + decisions prod-like du modele de donnees (drop commande_event, nommage EN, TVA par produit apres fact-check BOFiP, perso menus/ingredients, allergenes, ~16 entites) | `feat/p1-conception` | | 2026-06-15 | [p3-throttle-pin-rg-t22](2026-06-15--p3-throttle-pin-rg-t22.md) | P3 securite : throttle du PIN d'action sensible (RG-T22) — design multi-agents + verification adversariale, dimension "utilisateur agissant", entite 22 `pin_throttle` | `feat/p3-pin-throttle` -> `dev` | +| 2026-06-16 | [audit-reel-livrables-p2-p3](2026-06-16--audit-reel-livrables-p2-p3.md) | Verification sur pieces des livrables du 2026-06-15 (sweep 10 dimensions + adversarial) : socle SbD confirme, miss confirmes par gravite (php.ini non deploye, CI sans tests DB, XSS kiosk, liens morts...) et remediations | `docs/journal-audit-2026-06-16` -> `dev` (PR #19/#20/#21) | *Mis a jour a chaque nouvelle entree.*