# Sécurité — n8n Pilot ## Modèle de menaces ### Acteurs et vecteurs | Menace | Impact | Probabilité | Mitigation | |--------|--------|-------------|-----------| | Vol de l'appareil Android | Accès aux credentials n8n | Moyen | Android Keystore chiffré, biométrie optionnelle | | Interception réseau (MITM) | Exposition de la clé API | Faible (TLS) | TLS obligatoire, refus HTTP | | Fuite du token HAProxy | Accès non autorisé à n8n | Moyen | Rotation régulière, token hors bundle | | Compromission du build APK | Backdoor dans l'app | Faible | Keystore signé, builds EAS reproductibles | | Brute force API | Épuisement quotas n8n | Faible | Rate limiting HAProxy (429) | | Logs applicatifs exposés | Fuite de secrets | Faible | Jamais de log de secrets, même en dev | --- ## Principes appliqués ### Least Privilege (moindre privilège) La clé API n8n doit être créée avec le **scope minimal** nécessaire : ``` Recommandé : ✓ workflows:list — lister les workflows ✓ workflows:read — lire les détails ✓ workflows:update — activer/désactiver (toggle) ✓ executions:list — voir l'historique ✓ executions:read — lire les logs ✓ executions:delete — supprimer des exécutions ✓ workflows:run — déclencher manuellement Non recommandé : ✗ credentials:* — inutile pour cette app ✗ users:* — inutile pour cette app ✗ admin:* — jamais ``` **Comment créer la clé** dans n8n : 1. Settings > n8n API 2. Create API Key 3. Nommer la clé "n8n-pilot-mobile" 4. Définir les scopes minimaux ci-dessus 5. Copier la clé — elle n'est affichée qu'une seule fois --- ### Defense in Depth (défense en profondeur) L'accès à l'API n8n passe par **deux barrières indépendantes** : ``` Requête → [TLS] → [X-App-Token HAProxy] → [X-N8N-API-KEY n8n] → Données ``` Si un token est compromis : - Compromission du `X-App-Token` seul → HAProxy bloque, n8n jamais atteint - Compromission de la clé API seul → sans le `X-App-Token`, HAProxy bloque à 403 - Les deux compromis → rotation immédiate des deux (procédures dans HAPROXY.md et BACKUP.md) --- ### Zero Trust (réseau local inclus) n8n ne doit **pas** être accessible directement sur le réseau, même en local. Toutes les requêtes passent par HAProxy qui valide le token. ``` # Bloquer l'accès direct au port n8n (iptables) iptables -A INPUT -p tcp --dport 5678 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 5678 -j DROP ``` --- ## Gestion des secrets — cycle de vie ### Stockage ``` ┌─────────────────────────────────────────────────────┐ │ Appareil Android │ │ ┌─────────────────────────────────────────────┐ │ │ │ Android Keystore (expo-secure-store) │ │ │ │ n8n_base_url → https://n8n.example.com │ │ │ │ n8n_api_key → clé API (chiffrée) │ │ │ │ n8n_app_token → token HAProxy (chiffré) │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ État React (Zustand) — en mémoire uniquement : │ │ config.baseUrl → copie non sensible │ │ config.isConfigured → booléen │ │ JAMAIS : apiKey, appToken en mémoire JS │ └─────────────────────────────────────────────────────┘ ``` ### Transit - Les secrets sont lus depuis le Keystore **à chaque requête** HTTP dans `client.ts` - Ils sont injectés dans les headers HTTP et **ne sont pas loggués** - Ils ne sont **jamais** : - Sérialisés dans AsyncStorage - Inclus dans des logs (même en dev) - Embarqués dans le bundle JS (`app.json`, `package.json`, code source) - Envoyés à des services tiers (analytics, crash reporters) ### Rotation | Secret | Fréquence recommandée | Procédure | |--------|-----------------------|-----------| | Clé API n8n | Tous les 180 jours, ou en cas de compromission | Créer nouvelle clé dans n8n, mettre à jour dans l'app | | X-App-Token | Tous les 90 jours | Voir docs/HAPROXY.md | | Keystore EAS | Jamais (sauf compromission) | Voir docs/BACKUP.md | --- ## Checklist avant mise en production ### Application - [ ] `app.json` : `userInterfaceStyle` = `"dark"` (pas d'info sensible en clair) - [ ] `.env` non commité dans git (`git status` ne montre pas `.env`) - [ ] Aucun `console.log` de valeurs sensibles dans le code - [ ] `__DEV__` gate sur tous les logs dans `errorHandler.ts` - [ ] Expo SDK à jour — vérifier les CVE : `npx expo-doctor` - [ ] Dépendances à jour : `npm audit` ### Infrastructure - [ ] HAProxy : TLS 1.2 minimum, TLS 1.0/1.1 désactivés - [ ] Certificat TLS valide et non expiré - [ ] n8n inaccessible directement sur le port 5678 depuis l'extérieur - [ ] Rate limiting HAProxy activé (429 configuré) - [ ] Logs HAProxy ne contiennent pas les valeurs des headers secrets ### n8n - [ ] Clé API avec scope minimal (voir § Least Privilege ci-dessus) - [ ] n8n mis à jour vers la dernière version stable - [ ] Sauvegardes n8n actives (workflows, credentials n8n) ### Appareil - [ ] Verrouillage d'écran activé (PIN, pattern ou biométrie) - [ ] Biométrie configurée dans l'app si disponible - [ ] Appareil Android 8+ (API 26+) pour garantir la robustesse du Keystore