# Rapport d'audit securite

Date : 2026-06-02

## Perimetre analyse

Audit statique du socle PHP/MySQL : front controller, routeur, sessions, authentification, ACL, vues, formulaires publics, uploads, depots PDO, back-office, journal d'audit, resolution multi-tenant et migrations.

Le depot contenait deja de nombreuses evolutions locales non validees. Les corrections ci-dessous sont additives et evitent toute suppression de donnees.

## Corrections realisees

### Critique et eleve

- Ajout de `POST /api/network/sync` avec authentification `Authorization: Bearer`, cles hachees SHA-256, revocation, limite de taille, validation JSON stricte, quota par client et reponses JSON sans details SQL.
- Provisionnement automatique des comptes par couple `network_id + external_id`. Aucun rattachement automatique n'est effectue sur le seul email : une collision ambigue bloque la synchronisation.
- Ajout des agences externes, rattachements agence-boutique, utilisateurs reseau, mappings de roles configurables, historique des changements d'agence et journaux de synchronisation.
- Reutilisation des tables metier existantes pour eviter une duplication de donnees : `shops` tient lieu de `network_shops`, `user_shop_memberships` de `network_shop_users` et `shop_products` du rattachement catalogue par boutique.
- Le mode `full` desactive logiquement les agences et utilisateurs absents. Aucune suppression physique n'est effectuee.
- Correction d'une redirection ouverte possible apres connexion boutique : une cible commencant par `//` ou contenant `\` est maintenant refusee.
- Protection de `/admin/pricing/quote`, auparavant accessible sans garde back-office, par la permission `pricing.master.manage`.
- Ajout de `public/uploads/.htaccess` pour interdire l'execution ou le service de fichiers actifs dans le repertoire d'uploads.

### Durcissement transverse

- Ajout d'une expiration de session par inactivite, configurable avec `SESSION_IDLE_TIMEOUT_SECONDS`.
- Conservation des protections deja presentes : cookies `HttpOnly`, `SameSite=Lax`, `Secure` sous HTTPS, mode strict PHP et regeneration apres connexion.
- Ajout de `last_login_at` sur `users`.
- Ajout de `system_logs` et enregistrement centralise des exceptions non gerees sans remplacer l'erreur d'origine.
- Ajout d'une CSP progressive en `Content-Security-Policy-Report-Only`, en complement de `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy` et `Permissions-Policy`.
- Ajout du helper central `e()` base sur `htmlspecialchars(..., ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')`.
- Ajout de traces d'authentification : succes, refus ACL, echec, quota atteint et deconnexion pour le back-office et la boutique.
- Ajout de honeypots publics et quotas sur l'inscription. Ajout d'un honeypot et d'une temporisation sur les demandes de devis.

## Protections existantes confirmees

- Requetes SQL majoritairement preparees avec PDO.
- CSRF centralise et verifie sur les actions d'ecriture inspectees.
- ACL back-office centralisees via `AdminGuard`, `AuthorizationService`, roles et permissions.
- Filtrage de perimetre reseau et boutique deja present dans les principaux depots et controleurs.
- Validation d'uploads deja existante : extension, MIME, taille, signature PDF, dimensions JPEG et nommage aleatoire.
- Audit fonctionnel existant via `audit_logs` et interface `/admin/audit`.
- Limitation des tentatives de connexion existante via `login_rate_limits`.

## Migration a appliquer

Executer apres sauvegarde :

```sql
source database/migrations/028_security_network_sync.sql;
```

Cette migration ajoute uniquement des colonnes, tables et index. Elle ne supprime aucune donnee.

## Fichiers principaux ajoutes ou modifies

- `database/migrations/028_security_network_sync.sql`
- `src/Modules/NetworkSync/`
- `src/Support/Logging/`
- `src/Core/Http/Request.php`
- `src/Core/Http/Response.php`
- `src/Core/Session/Session.php`
- `src/Core/Application.php`
- `public/uploads/.htaccess`
- `templates/admin/networks/sync.php`
- `API_NETWORK_SYNC.md`
- `SECURITY_TEST_CHECKLIST.md`

## Risques restants

- Appliquer la migration sur une copie de production et tester les volumes reels avant de l'executer en production.
- Passer `APP_DEBUG=false` en production et verifier que le vhost pointe uniquement vers `public/`.
- Observer les rapports CSP avant de convertir la politique en mode bloquant.
- Realiser une revue XSS manuelle exhaustive des vues historiques : l'audit statique confirme un usage large de `htmlspecialchars`, mais les nombreux templates existants meritent un test navigateur complet.
- Tester les ACL avec un compte par role et par reseau afin de confirmer l'absence d'IDOR sur chaque ecran metier.
- Ajouter une politique de retention et une interface restreinte pour `system_logs` si une consultation back-office est souhaitee.
- Stocker les secrets SSO existants avec chiffrement applicatif ou coffre de secrets : la table historique conserve encore `client_secret`.
- Isoler idealement les fichiers non publics hors de `public/uploads` et les servir via un controleur autorise lorsque leur confidentialite l'exige.

## Verification effectuee

- Analyse syntaxique PHP 8.2 sur `src`, `bootstrap`, `config`, `public`, `templates` et `tests` : OK.
- `tests/host_normalizer_regression.php` : OK.
- `tests/security_http_regression.php` : OK.
- `tests/network_sync_regression.php` : OK dans une base MySQL temporaire isolee.
- `tests/personalization_regression.php` : bloque localement par un refus d'ecriture dans `public/uploads/orders`.
