88cf6458d0
Application web d'inventaire réseau manuel avec FastAPI, Vue 3 et Docker. Inclut l'authentification JWT, la découverte ICMP, et la topologie en cards CSS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
184 lines
15 KiB
Markdown
184 lines
15 KiB
Markdown
# Plan d'action securite pour Claude Code
|
|
|
|
Objectif: corriger les ecarts de securite de base identifies dans `SECURITY_AUDIT_BASE.md`, sans refonte fonctionnelle inutile. Chaque tache est atomique et doit etre livree avec tests.
|
|
|
|
## SEC-FIX-001
|
|
|
|
Priorite: P0
|
|
Fichier(s) a modifier: `backend/main.py`, `backend/routers/auth.py`, `docker-compose.yml`, `.env.example`, `CLAUDE.md`, `AGENTS.md`, `docs/backend.md`, `docs/extending.md`
|
|
Probleme: compte de bootstrap `admin/admin` cree automatiquement au premier demarrage, sans changement force.
|
|
Correction attendue: conserver le bootstrap seulement si un changement de mot de passe est force au premier login. Variante plus robuste: remplacer le mot de passe fixe par une initialisation sure via variable `INITIAL_ADMIN_PASSWORD` ou secret Docker obligatoire si aucun utilisateur n'existe.
|
|
Risque couvert: compromission immediate d'une instance neuve.
|
|
Critere d'acceptation: une base vide peut creer `admin/admin` uniquement avec un etat `must_change_password`; tant que le mot de passe n'est pas change, seuls les endpoints necessaires au changement de compte sont accessibles. Si l'option `INITIAL_ADMIN_PASSWORD` est retenue, `admin/admin` n'est plus cree.
|
|
Tests recommandes: test unitaire de `_migrate_users()`; test premier login `admin/admin` redirige vers changement obligatoire; test acces CRUD refuse avant changement; test acces CRUD autorise apres changement.
|
|
|
|
## SEC-FIX-002
|
|
|
|
Priorite: P1
|
|
Fichier(s) a modifier: `backend/routers/auth.py`, `backend/rate_limit.py` (nouveau si necessaire), `frontend/nginx.conf`, `backend/requirements.txt`
|
|
Probleme: aucune limitation de tentatives sur `/api/auth/login`.
|
|
Correction attendue: ajouter une limitation par IP et par username avec fenetre temporelle, ou configurer `limit_req` Nginx plus une protection API. Les erreurs doivent rester generiques.
|
|
Risque couvert: bruteforce et credential stuffing.
|
|
Critere d'acceptation: apres N echecs rapproches, les tentatives suivantes recoivent une reponse de limitation temporaire; une connexion legitime fonctionne apres expiration de la fenetre.
|
|
Tests recommandes: tests API simulant echecs successifs, reset apres fenetre, non-enumeration des comptes.
|
|
|
|
## SEC-FIX-003
|
|
|
|
Priorite: P1
|
|
Fichier(s) a modifier: `backend/routers/auth.py`, `frontend/src/components/AccountModal.vue`, `frontend/src/i18n.js`
|
|
Probleme: `new_password` et `new_username` ne sont pas valides robustement cote serveur.
|
|
Correction attendue: imposer une longueur minimale de mot de passe, refuser les mots de passe evidents, borner/normaliser le username, retourner des messages localisables.
|
|
Risque couvert: prise de compte par mot de passe faible et donnees auth incoherentes.
|
|
Critere d'acceptation: les mots de passe trop courts/faibles sont refuses cote API; le frontend affiche une erreur claire; les usernames invalides sont refuses.
|
|
Tests recommandes: tests API pour password vide, court, faible, valide; username vide, trop long, caracteres invalides, doublon.
|
|
|
|
## SEC-FIX-004
|
|
|
|
Priorite: P1
|
|
Fichier(s) a modifier: `backend/routers/auth.py`, `backend/models.py`, `backend/main.py`, `frontend/src/auth.js`, `frontend/src/api.js`, `frontend/src/components/LoginPage.vue`, `frontend/src/components/AccountModal.vue`, `frontend/nginx.conf`
|
|
Probleme: JWT stocke en `localStorage`, duree 7 jours, pas d'invalidation apres changement de mot de passe.
|
|
Correction attendue: migrer vers cookie `HttpOnly`, `Secure`, `SameSite=Lax` ou `Strict`; ajouter version de session/token dans la base; invalider les anciens tokens apres changement de mot de passe. Si cookie impossible immediatement, reduire l'expiration et ajouter une version de session.
|
|
Risque couvert: vol/rejeu de token apres XSS ou poste compromis.
|
|
Critere d'acceptation: le token n'est plus lisible par JavaScript dans le mode cible; un changement de mot de passe invalide les tokens precedents; logout supprime la session/cookie.
|
|
Tests recommandes: tests login/me/logout, changement de mot de passe puis ancien token refuse, verification flags `Set-Cookie`.
|
|
|
|
## SEC-FIX-005
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `backend/main.py`, `.env.example`, `docker-compose.yml`, `docs/backend.md`
|
|
Probleme: CORS ouvert a toutes origines alors que l'application est prevue en local derriere reverse-proxy.
|
|
Correction attendue: documenter que le backend reste interne et que le navigateur accede a `/api/` en meme origine via reverse-proxy. Supprimer CORS si inutile, ou ajouter `ALLOWED_ORIGINS` configurable pour les cas ou une origine externe est necessaire.
|
|
Risque couvert: publication accidentelle de l'API interne ou configuration dangereuse si l'auth migre vers cookies.
|
|
Critere d'acceptation: le mode recommande n'expose pas directement le backend; la doc explique quand CORS est necessaire; si `ALLOWED_ORIGINS` est ajoute, une origine non autorisee ne recoit pas d'en-tetes CORS permissifs.
|
|
Tests recommandes: test API avec headers `Origin` autorisee/non autorisee si CORS conserve; verification de la configuration Compose/reverse-proxy documentee.
|
|
|
|
## SEC-FIX-006
|
|
|
|
Priorite: P1
|
|
Fichier(s) a modifier: `backend/routers/discovery.py`, `frontend/src/components/DiscoveryModal.vue`, `frontend/src/api.js`, `frontend/src/i18n.js`
|
|
Probleme: `/scan` et `/ping` acceptent des cibles arbitraires et insuffisamment limitees.
|
|
Correction attendue: valider `ips` avec `ipaddress.ip_address`, valider `dns_server`, limiter le nombre total d'IP par requete, limiter le nombre de targets, autoriser uniquement les CIDR presents en base ou explicitement configures, ajouter rate limit.
|
|
Risque couvert: SSRF/reconnaissance interne et deni de service par surcharge de scans.
|
|
Critere d'acceptation: IP/CIDR/DNS invalides refuses; targets hors perimetre refusees; total d'adresses plafonne; les scans legitimes de VLAN configures fonctionnent.
|
|
Tests recommandes: tests API `ping` liste vide, liste trop grande, IP invalide, IP valide; tests `scan` CIDR trop large, target hors inventaire, DNS invalide, cas nominal.
|
|
|
|
## SEC-FIX-007
|
|
|
|
Priorite: P1
|
|
Fichier(s) a modifier: `backend/routers/devices.py`, `backend/routers/vlans.py`, `backend/routers/links.py`, `frontend/src/components/DeviceManager.vue`, `frontend/src/components/VlanManager.vue`, `frontend/src/components/TopologyGraph.vue`, `frontend/src/i18n.js`
|
|
Probleme: schemas metier trop permissifs.
|
|
Correction attendue: ajouter contraintes Pydantic v2: `Field(max_length=...)`, enums/Literal pour device type, virt type et link type, validation IP/CIDR, couleur hex, URL `http/https` uniquement. Ajouter `rel="noreferrer noopener"` sur liens externes.
|
|
Risque couvert: XSS via URL dangereuse, donnees incoherentes, injection future, DoS par champs enormes.
|
|
Critere d'acceptation: l'API refuse les valeurs hors enum, URL non http/https, CIDR/IP/couleur invalides et champs trop longs; l'UI affiche les erreurs.
|
|
Tests recommandes: tests API par champ invalide/valide; tests frontend de rendu lien externe avec `noreferrer`.
|
|
|
|
## SEC-FIX-008
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `frontend/nginx.conf`, `frontend/index.html`, `frontend/src/App.vue` si ajustements CSP necessaires
|
|
Probleme: absence d'en-tetes de securite navigateur dans la configuration fournie; ils peuvent etre portes par le reverse-proxy frontal.
|
|
Correction attendue: fournir une configuration de reference reverse-proxy ou ajouter dans `frontend/nginx.conf` une CSP minimale, `X-Content-Type-Options: nosniff`, `Referrer-Policy`, `Permissions-Policy`, et protection anti-framing via CSP `frame-ancestors` ou `X-Frame-Options`.
|
|
Risque couvert: impact XSS, clickjacking, sniffing MIME, fuite referrer.
|
|
Critere d'acceptation: les en-tetes sont presents sur `/` et assets; l'application build fonctionne sans violation CSP critique.
|
|
Tests recommandes: `curl -I` sur `/`; test navigateur console sans erreurs CSP bloquantes; build Vite.
|
|
|
|
## SEC-FIX-009
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `docker-compose.yml`, `frontend/nginx.conf`, `docs/architecture.md`, `.env.example`
|
|
Probleme: TLS est delegue au reverse-proxy, mais le contrat de deploiement n'est pas documente.
|
|
Correction attendue: documenter explicitement que le mode actuel est local derriere reverse-proxy; fournir un exemple de deploiement derriere reverse-proxy TLS; recommander le bind `127.0.0.1:8080:80` si seul le proxy local doit consommer l'application.
|
|
Risque couvert: interception d'identifiants et tokens sur reseau non fiable.
|
|
Critere d'acceptation: la documentation exige HTTPS au niveau reverse-proxy pour tout acces non local; un exemple utilisable indique les variables et headers proxy necessaires; Compose n'encourage pas une exposition directe involontaire.
|
|
Tests recommandes: revue doc; test login via reverse proxy TLS si un profil est ajoute.
|
|
|
|
## SEC-FIX-010
|
|
|
|
Priorite: P1
|
|
Fichier(s) a modifier: `backend/routers/auth.py`, `docker-compose.yml`, `.gitignore`, `.env.example`, `docs/architecture.md`
|
|
Probleme: `data/secret_key.txt` est dans un bind mount projet et peut etre lisible localement.
|
|
Correction attendue: charger `SECRET_KEY` depuis secret Docker ou env obligatoire en production; creer les fichiers generes avec permissions `0600`; ignorer `db_data/`; documenter rotation de cle.
|
|
Risque couvert: fuite de cle JWT et forge de tokens.
|
|
Critere d'acceptation: nouveau fichier secret cree en `0600`; `db_data/` ignore; production documentee avec secret externe; absence de secret reel dans exemples.
|
|
Tests recommandes: test unitaire ou integration verifiant permissions; verification `.gitignore`; demarrage avec `SECRET_KEY`.
|
|
|
|
## SEC-FIX-011
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `backend/Dockerfile`, `frontend/Dockerfile`, `docker-compose.yml`
|
|
Probleme: conteneurs lances sans durcissement explicite.
|
|
Correction attendue: executer backend et frontend en non-root si compatible, ajouter `cap_drop: [ALL]`, garder `NET_RAW` uniquement backend, `security_opt: no-new-privileges:true`, healthchecks, limites ressources, filesystem readonly avec volumes temporaires necessaires.
|
|
Risque couvert: impact accru en cas de compromission de conteneur.
|
|
Critere d'acceptation: les services demarrent et fonctionnent avec utilisateur non-root et privileges reduits; ping reste fonctionnel si active.
|
|
Tests recommandes: `docker compose up --build -d`, test login/CRUD/ping, verification `docker compose ps`, inspection utilisateur/capabilities.
|
|
|
|
## SEC-FIX-012
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `backend/routers/auth.py`, `backend/routers/devices.py`, `backend/routers/vlans.py`, `backend/routers/links.py`, `backend/routers/discovery.py`, `frontend/nginx.conf`
|
|
Probleme: absence de logs securite structures.
|
|
Correction attendue: journaliser login reussi/echec, changement username/password, scans, imports/creates/deletes, erreurs de validation et rate limits, sans jamais logger mots de passe/tokens.
|
|
Risque couvert: detection et investigation insuffisantes.
|
|
Critere d'acceptation: chaque evenement sensible produit un log structure avec action, resultat, username, IP client fiable, compteurs utiles.
|
|
Tests recommandes: tests API capturant logs; verification absence de secrets dans logs.
|
|
|
|
## SEC-FIX-013
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `backend/database.py`, `backend/models.py`, `backend/routers/devices.py`, `backend/routers/vlans.py`, `backend/routers/links.py`
|
|
Probleme: SQLite n'enforce pas les foreign keys.
|
|
Correction attendue: activer `PRAGMA foreign_keys=ON` sur chaque connexion via event SQLAlchemy; ajuster cascades/ondelete si necessaire.
|
|
Risque couvert: incoherence et corruption logique des donnees.
|
|
Critere d'acceptation: creation d'une interface avec `device_id` inexistant echoue; suppression VLAN/device conserve le comportement fonctionnel attendu.
|
|
Tests recommandes: tests DB d'integrite FK; tests suppression VLAN/device/link.
|
|
|
|
## SEC-FIX-014
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `frontend/Dockerfile`, `frontend/package.json`, `frontend/package-lock.json`, `backend/requirements.txt`, documentation CI
|
|
Probleme: supply chain incomplete, `npm install`, dependance `cytoscape` inutilisee.
|
|
Correction attendue: remplacer `npm install` par `npm ci`; supprimer `cytoscape` si vraiment inutilise; ajouter scripts/documentation pour `npm audit` et audit Python; conserver compatibilite passlib/bcrypt.
|
|
Risque couvert: composants vulnerables/obsoletes et builds non reproductibles.
|
|
Critere d'acceptation: build Docker frontend utilise le lockfile; dependances inutilisees supprimees; procedure SCA documentee.
|
|
Tests recommandes: `docker compose build frontend`; `npm run build`; audit dependances dans CI ou local.
|
|
|
|
## SEC-FIX-015
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `frontend/src/App.vue`, `backend/routers/devices.py`, `backend/routers/vlans.py`, `frontend/src/i18n.js`
|
|
Probleme: import JSON sans schema, limites ni bilan d'erreurs.
|
|
Correction attendue: limiter taille fichier/nombre d'objets, valider structure avant import, afficher un resume des erreurs, ne pas ignorer silencieusement les echecs.
|
|
Risque couvert: deni de service local, import incoherent, donnees dangereuses passant par CRUD.
|
|
Critere d'acceptation: fichier trop gros refuse; schema invalide refuse; import partiel affiche les erreurs; import valide fonctionne.
|
|
Tests recommandes: tests frontend unitaires pour parsing/validation; tests manuels import valide/invalide/gros.
|
|
|
|
## SEC-FIX-016
|
|
|
|
Priorite: P3
|
|
Fichier(s) a modifier: `frontend/src/App.vue`
|
|
Probleme: `v-html` utilise pour des icones statiques de navigation.
|
|
Correction attendue: remplacer par interpolation texte ou composants d'icones sans HTML injecte.
|
|
Risque couvert: reduction defense-in-depth du risque XSS futur.
|
|
Critere d'acceptation: aucun `v-html` ne reste dans `App.vue`; les icones de navigation s'affichent toujours.
|
|
Tests recommandes: `rg "v-html" frontend/src`; test visuel rapide.
|
|
|
|
## SEC-FIX-017
|
|
|
|
Priorite: P3
|
|
Fichier(s) a modifier: `backend/main.py`, `frontend/nginx.conf`, `docker-compose.yml`, `docs/backend.md`
|
|
Probleme: `/api/health` est public; c'est acceptable pour un healthcheck local/reverse-proxy mais doit rester assume.
|
|
Correction attendue: documenter que l'endpoint est volontairement public et minimal, ou le restreindre au reverse-proxy si souhaite. Ne pas exposer d'informations de version.
|
|
Risque couvert: exposition inutile d'informations de disponibilite si le proxy publie trop largement les endpoints internes.
|
|
Critere d'acceptation: decision documentee; endpoint ne retourne toujours aucun detail sensible; si restreint, le healthcheck Compose/reverse-proxy fonctionne.
|
|
Tests recommandes: `curl /api/health` selon mode attendu; test healthcheck Docker.
|
|
|
|
## SEC-FIX-018
|
|
|
|
Priorite: P2
|
|
Fichier(s) a modifier: `README.md`, `.env.example`, `CLAUDE.md`, `AGENTS.md`, `docs/architecture.md`, `docs/backend.md`
|
|
Probleme: documentation securite et configuration d'environnement incompletes.
|
|
Correction attendue: ajouter README et `.env.example` sans secrets reels; documenter `SECRET_KEY`, `INITIAL_ADMIN_PASSWORD`, `ALLOWED_ORIGINS`, TLS, stockage des donnees, rotation de cle, sauvegarde/restauration et profil dev/prod.
|
|
Risque couvert: mauvaises configurations deployees par defaut.
|
|
Critere d'acceptation: un nouvel operateur peut deployer sans identifiants par defaut ni secret genere dans le depot; les differences dev/prod sont explicites.
|
|
Tests recommandes: revue doc; demarrage Compose avec variables de `.env.example` adaptees.
|