# RAPPORT D'AUDIT SÉCURITÉ & LOGS - VWB RPA Vision v3 **Date**: 14 janvier 2026 **Auteur**: Claude (revue automatisée) **Contexte**: Environnements sensibles (Santé, Défense, Administration) **Mode**: Revue uniquement - Aucun code modifié **Statut**: À CORRIGER APRÈS LES DÉMOS --- ## SCORE GLOBAL : 3/10 - NON PRÊT POUR PRODUCTION SENSIBLE > **Note**: Ce rapport est à traiter APRÈS les démonstrations en cours. > Les corrections de sécurité peuvent impacter le fonctionnement actuel. --- ## TABLE DES MATIÈRES 1. [Vulnérabilités Critiques](#1-vulnérabilités-critiques) 2. [Problèmes Logs & Traçabilité](#2-problèmes-logs--traçabilité) 3. [Headers Sécurité Manquants](#3-headers-sécurité-manquants) 4. [Endpoints Non Protégés](#4-endpoints-non-protégés) 5. [Conformité Réglementaire](#5-conformité-réglementaire) 6. [Plan de Remédiation](#6-plan-de-remédiation) 7. [Détails Techniques Complets](#7-détails-techniques-complets) --- ## 1. VULNÉRABILITÉS CRITIQUES ### Résumé (6 vulnérabilités critiques) | # | Vulnérabilité | Fichier | Ligne | Impact | |---|---------------|---------|-------|--------| | 1 | Tokens de production hardcodés | `core/security/api_tokens.py` | 93-96 | Compromis total auth | | 2 | CORS = "*" partout | `backend/app.py` | 34 | CSRF, accès cross-origin | | 3 | Zéro authentification sur /api/* | `backend/api/workflows.py` | - | Exécution workflows non autorisée | | 4 | SECRET_KEY par défaut | `backend/app.py` | 24 | Sessions forgées | | 5 | WebSocket sans auth | `backend/api/websocket_handlers.py` | - | Espionnage temps réel | | 6 | Path traversal | `backend/services/serialization.py` | 115 | Lecture/écriture fichiers système | ### 1.1 Tokens de Production Hardcodés (CRITIQUE) **Fichier**: `/home/dom/ai/rpa_vision_v3/core/security/api_tokens.py` lignes 93-109 ```python # Temporary fix: Add production tokens directly prod_admin_token = "73cf0db73f9a5064e79afebba96c85338be65cc2060b9c1d42c3ea5dd7d4e490" prod_readonly_token = "7eea1de415cc69c02381ce09ff63aeebf3e1d9b476d54aa6730ba9de849e3dc6" self.admin_tokens.add(prod_admin_token) self.read_only_tokens.add(prod_readonly_token) ``` **Problème**: - Tokens de production en dur dans le code source - Tokens visibles dans les dépôts Git - Réutilisés pour tous les environnements - Commentaires "Temporary fix" indiquant du code en attente **Impact**: Compromis complet de l'authentification en production **Correction recommandée**: ```python # Utiliser UNIQUEMENT les variables d'environnement admin_token = os.getenv("RPA_TOKEN_ADMIN") readonly_token = os.getenv("RPA_TOKEN_READONLY") if not admin_token or not readonly_token: if os.getenv('ENVIRONMENT') == 'production': raise ValueError("Tokens must be configured via environment variables") ``` ### 1.2 CORS Ouvert à Tous (CRITIQUE) **Fichiers impactés**: - `/home/dom/ai/rpa_vision_v3/visual_workflow_builder/backend/app.py:34-40` - `/home/dom/ai/rpa_vision_v3/visual_workflow_builder/backend/app_lightweight.py:512-516` ```python # SocketIO socketio = SocketIO( app, cors_allowed_origins="*", # VULNÉRABLE async_mode='threading' ) # Flask CORS CORS(app, origins="*", # VULNÉRABLE methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["Content-Type", "Authorization", "Accept", "X-Requested-With"], supports_credentials=False) ``` **Correction recommandée**: ```python CORS_ORIGINS = os.getenv('CORS_ORIGINS', 'http://localhost:3000').split(',') socketio = SocketIO( app, cors_allowed_origins=CORS_ORIGINS, async_mode='threading' ) CORS(app, origins=CORS_ORIGINS, methods=["GET", "POST", "PUT", "DELETE"], allow_headers=["Content-Type", "Authorization"], supports_credentials=True, max_age=3600) ``` ### 1.3 SECRET_KEY par Défaut (CRITIQUE) **Fichier**: `/home/dom/ai/rpa_vision_v3/visual_workflow_builder/backend/app.py:24` ```python app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production') ``` **Correction recommandée**: ```python secret_key = os.getenv('SECRET_KEY') if not secret_key or 'change-in-production' in secret_key: if os.getenv('ENVIRONMENT') == 'production': raise ValueError("SECRET_KEY must be set to a secure value in production") secret_key = 'dev-only-key' app.config['SECRET_KEY'] = secret_key ``` ### 1.4 WebSocket Sans Authentification (CRITIQUE) **Fichier**: `/home/dom/ai/rpa_vision_v3/visual_workflow_builder/backend/api/websocket_handlers.py` ```python @socketio.on('connect') def handle_connect(): client_id = request.sid emit('connected', {...}) # AUCUNE VÉRIFICATION D'AUTH ``` **Correction recommandée**: ```python @socketio.on('connect') def handle_connect(auth): token = auth.get('token') if auth else None if not token or not validate_token(token): return False # Refuse la connexion # ... reste du code ``` ### 1.5 Path Traversal (CRITIQUE) **Fichier**: `/home/dom/ai/rpa_vision_v3/visual_workflow_builder/backend/services/serialization.py:115-118` ```python def _path(self, workflow_id: str) -> str: safe_id = "".join(c for c in workflow_id if c.isalnum() or c in ("_", "-")) or workflow_id return os.path.join(self.root_dir, f"{safe_id}.json") ``` **Problème**: Le fallback `or workflow_id` contourne le filtre si tous les caractères sont supprimés. **Correction recommandée**: ```python from pathlib import Path def _path(self, workflow_id: str) -> str: # Filtrer strictement safe_id = "".join(c for c in workflow_id if c.isalnum() or c == "_") if not safe_id: safe_id = "default_workflow" # Vérifier que le chemin reste dans root_dir file_path = Path(self.root_dir) / f"{safe_id}.json" resolved = file_path.resolve() # Sécurité: vérifier qu'on ne sort pas du répertoire if not str(resolved).startswith(str(Path(self.root_dir).resolve())): raise ValueError("Invalid workflow ID - path traversal detected") return str(file_path) ``` ### 1.6 Mode Debug Activable en Production (HAUTE) **Fichier**: `/home/dom/ai/rpa_vision_v3/visual_workflow_builder/backend/app.py:185-193` ```python socketio.run( app, host='0.0.0.0', port=port, debug=debug, use_reloader=debug, allow_unsafe_werkzeug=True # DANGEREUX EN PRODUCTION ) ``` --- ## 2. PROBLÈMES LOGS & TRAÇABILITÉ ### 2.1 Lacunes Identifiées | Lacune | Sévérité | Conformité impactée | |--------|----------|---------------------| | `user_id` toujours `null` dans les logs | CRITIQUE | HIPAA, RGPD, ISO 27001 | | Pas d'audit trail workflow (qui/quoi/quand) | HAUTE | Tous secteurs | | Logs corrompus détectés (`logs/0.log`) | MOYENNE | Intégrité données | | Pas de rotation logs application | HAUTE | Disk full possible | | Rétention max 100MB (vs 7 ans HIPAA) | CRITIQUE | Santé | | Stack traces exposées en réponse API | HAUTE | OWASP | | IPs partiellement masquées (3 octets visibles) | MOYENNE | RGPD | ### 2.2 Structure de Log Actuelle (Insuffisante) **Fichier**: `/home/dom/ai/rpa_vision_v3/core/security/audit_log.py` ```json { "event_type": "api_access", "timestamp": "2026-01-06T00:59:45.467453Z", "message": "request_success", "user_id": null, // TOUJOURS NULL - PROBLÈME "ip_address": "127.0.0.xxx", // Masquage insuffisant (3 octets visibles) "endpoint": "/api/traces/status", "method": "GET", "success": true } ``` ### 2.3 Structure de Log Requise (HIPAA/RGPD) ```json { "event_type": "data_access", "timestamp": "2026-01-14T10:30:00.123456Z", "user_id": "admin@example.com", // OBLIGATOIRE "session_id": "sess_abc123", // Pour corrélation "correlation_id": "req_999", // Pour traçage distribué "action": "read_workflow", "resource_id": "workflow_123", "resource_type": "workflow", "ip_address": "192.168.x.x", // 2 octets max visibles "user_agent": "Mozilla/5.0...", "data_classification": "SENSITIVE", // Classification données "duration_ms": 234, "status": "success", "changes": { // Pour modifications "before": {...}, "after": {...} }, "signature": "hmac_sha256_..." // Immuabilité audit trail } ``` ### 2.4 Logs Corrompus Détectés **Fichier**: `/home/dom/ai/rpa_vision_v3/logs/0.log` ``` 2025-12-13 13:41:37,006 - rpa.0 - INFO - vÏÊ « ← CORRUPTION ENCODAGE 2025-12-13 13:41:37,009 - rpa.0 - ERROR - ← MESSAGE VIDE ``` ### 2.5 Configuration Rotation Actuelle **Fichier**: `/home/dom/ai/rpa_vision_v3/core/security/audit_log.py:68-106` ```python self.log_dir = Path(os.getenv("AUDIT_LOG_DIR", "logs/audit")) self.max_file_size = int(os.getenv("AUDIT_LOG_MAX_SIZE", "10485760")) # 10MB self.max_files = int(os.getenv("AUDIT_LOG_MAX_FILES", "10")) ``` **Problèmes**: - Total max: 100MB (10 fichiers x 10MB) - Pas de rétention temporelle (HIPAA exige 7 ans) - Pas de compression des archives - Logs applicatifs non rotatés --- ## 3. HEADERS SÉCURITÉ MANQUANTS | Header | État | Risque | Correction | |--------|------|--------|------------| | `Strict-Transport-Security` | ABSENT | Downgrade HTTPS | `max-age=31536000; includeSubDomains` | | `Content-Security-Policy` | ABSENT | XSS | `default-src 'self'` | | `X-Frame-Options` | ABSENT | Clickjacking | `DENY` | | `X-Content-Type-Options` | ABSENT | MIME sniffing | `nosniff` | | `X-XSS-Protection` | ABSENT | XSS legacy | `1; mode=block` | | `Referrer-Policy` | ABSENT | Fuite referrer | `strict-origin-when-cross-origin` | **Correction recommandée** (à ajouter dans `app.py`): ```python @app.after_request def set_security_headers(response): response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' response.headers['Content-Security-Policy'] = "default-src 'self'; script-src 'self' 'unsafe-inline'" response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'DENY' response.headers['X-XSS-Protection'] = '1; mode=block' response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin' return response ``` --- ## 4. ENDPOINTS NON PROTÉGÉS ### 4.1 Backend VWB (`/api/*`) | Méthode | Endpoint | Risque | Auth requise | |---------|----------|--------|--------------| | GET | `/api/workflows/` | Enumération | Oui | | POST | `/api/workflows/` | Création non autorisée | Oui | | GET | `/api/workflows/` | Lecture données | Oui | | PUT | `/api/workflows/` | Modification | Oui | | DELETE | `/api/workflows/` | Suppression | Oui | | POST | `/api/screen-capture` | Capture écran | Oui | ### 4.2 Dashboard Web | Méthode | Endpoint | Risque | Auth requise | |---------|----------|--------|--------------| | POST | `/api/workflows//execute` | **EXÉCUTION SANS AUTH** | CRITIQUE | | POST | `/api/agent/sessions//process` | Traitement sessions | Oui | | GET | `/api/agent/sessions` | Enumération | Oui | | GET | `/api/logs` | **LOGS SYSTÈME PUBLICS** | CRITIQUE | | POST | `/api/logs/download` | Téléchargement logs | Oui | | GET | `/api/system/status` | Info système | Oui | ### 4.3 Endpoints Debug à Supprimer en Production **Fichier**: `/home/dom/ai/rpa_vision_v3/core/security/fastapi_security.py:61` ```python DEFAULT_PUBLIC_PATHS = { "/api/traces/debug-auth", # EXPOSÉ - À RETIRER "/api/traces/debug-env", # EXPOSÉ - À RETIRER } ``` --- ## 5. CONFORMITÉ RÉGLEMENTAIRE ### 5.1 Matrice de Conformité | Standard | Exigence | État | Gap | |----------|----------|------|-----| | **HIPAA** | Rétention 7 ans | ❌ | Max 100 MB | | **HIPAA** | User audit trail | ❌ | user_id = null | | **HIPAA** | Data access logs | ❌ | Non implémenté | | **RGPD** | Droit à l'oubli | ❌ | Pas de TTL/purge | | **RGPD** | PII masquage | ❌ | Loggé en clair | | **RGPD** | Consentement logs | ❌ | Non tracé | | **SOC 2** | Log retention | ❌ | 100 MB insuffisant | | **SOC 2** | Integrity verification | ❌ | JSONL non signé | | **ISO 27001** | Change tracking | ❌ | Pas de before/after | | **ISO 27001** | Admin actions | ~ | Partiel | ### 5.2 Verdict par Secteur | Secteur | État | Bloqueurs principaux | |---------|------|----------------------| | **Santé (HIPAA)** | ❌ NO-GO | user_id null, rétention insuffisante | | **Défense** | ❌ NO-GO | Pas de classification, pas de clearance | | **Administration (RGPD)** | ❌ NO-GO | PII en clair, pas de droit à l'oubli | | **Entreprise standard** | ⚠️ RISQUÉ | Authentification manquante | --- ## 6. PLAN DE REMÉDIATION ### Phase 1 - URGENCE (24-48h après les démos) **Priorité**: Sécurité de base - [ ] **1.1** Supprimer tokens hardcodés de `api_tokens.py` (lignes 93-109) - [ ] **1.2** Configurer CORS avec origines explicites (pas "*") - [ ] **1.3** Changer SECRET_KEY avec valeur sécurisée - [ ] **1.4** Masquer erreurs détaillées en production - [ ] **1.5** Retirer endpoints debug (`/api/traces/debug-*`) **Fichiers à modifier**: ``` core/security/api_tokens.py visual_workflow_builder/backend/app.py visual_workflow_builder/backend/app_lightweight.py core/security/fastapi_security.py ``` ### Phase 2 - Court terme (1-2 semaines) **Priorité**: Authentification & Protection - [ ] **2.1** Ajouter middleware d'authentification sur `/api/*` - [ ] **2.2** Implémenter rate limiting (flask-limiter) - [ ] **2.3** Authentifier connexions WebSocket - [ ] **2.4** Ajouter headers de sécurité - [ ] **2.5** Corriger path traversal dans serialization.py - [ ] **2.6** Valider uploads (taille, type, contenu) **Exemple middleware auth**: ```python from functools import wraps def require_auth(f): @wraps(f) def decorated(*args, **kwargs): token = request.headers.get('Authorization', '').replace('Bearer ', '') if not token or not validate_token(token): return jsonify({'error': 'Unauthorized'}), 401 return f(*args, **kwargs) return decorated # Appliquer sur les routes @app.route('/api/workflows/', methods=['POST']) @require_auth def create_workflow(): ... ``` ### Phase 3 - Moyen terme (1 mois) **Priorité**: Logs & Audit - [ ] **3.1** Ajouter `user_id` aux logs d'audit - [ ] **3.2** Implémenter audit trail workflow complet - [ ] **3.3** Rotation et rétention logs conforme (7 ans si HIPAA) - [ ] **3.4** Masquage automatique PII - [ ] **3.5** Signature des logs pour immuabilité - [ ] **3.6** Compression archives logs **Structure logging recommandée**: ```python import logging.config LOGGING_CONFIG = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'json': { 'class': 'pythonjsonlogger.jsonlogger.JsonFormatter', 'format': '%(timestamp)s %(level)s %(name)s %(message)s' } }, 'handlers': { 'rotating_file': { 'class': 'logging.handlers.RotatingFileHandler', 'filename': 'logs/vwb.log', 'maxBytes': 10485760, # 10MB 'backupCount': 100, # 1GB total 'formatter': 'json' } }, 'root': { 'level': 'INFO', 'handlers': ['rotating_file'] } } logging.config.dictConfig(LOGGING_CONFIG) ``` ### Phase 4 - Long terme (2-3 mois) **Priorité**: Conformité complète - [ ] **4.1** Intégration SIEM (syslog/ELK/Splunk) - [ ] **4.2** RBAC (Role-Based Access Control) - [ ] **4.3** Chiffrement données au repos - [ ] **4.4** Backup et recovery audit trail - [ ] **4.5** Penetration testing - [ ] **4.6** Documentation sécurité --- ## 7. DÉTAILS TECHNIQUES COMPLETS ### 7.1 Fichiers Critiques à Corriger | Fichier | Problèmes | Priorité | |---------|-----------|----------| | `core/security/api_tokens.py` | Tokens hardcodés | P1 | | `backend/app.py` | CORS, SECRET_KEY, debug, auth | P1 | | `backend/app_lightweight.py` | CORS | P1 | | `backend/api/websocket_handlers.py` | Auth WebSocket | P1 | | `backend/services/serialization.py` | Path traversal | P1 | | `core/security/audit_log.py` | user_id, masquage IP | P2 | | `backend/api/workflows.py` | Validation entrées | P2 | | `core/security/fastapi_security.py` | Endpoints debug | P2 | ### 7.2 Variables d'Environnement Requises ```bash # Production - À configurer OBLIGATOIREMENT SECRET_KEY= TOKEN_SECRET_KEY= RPA_TOKEN_ADMIN= RPA_TOKEN_READONLY= CORS_ORIGINS=https://app.example.com,https://admin.example.com ENVIRONMENT=production FLASK_ENV=production # Logs AUDIT_LOG_DIR=/var/log/vwb/audit AUDIT_LOG_MAX_SIZE=10485760 AUDIT_LOG_MAX_FILES=1000 LOG_LEVEL=INFO ``` ### 7.3 Commandes de Génération de Secrets ```bash # Générer un nouveau SECRET_KEY python -c "import secrets; print(secrets.token_hex(32))" # Générer un nouveau token admin python -c "import secrets; print(secrets.token_hex(32))" # Vérifier les permissions des fichiers .env chmod 600 .env.local chown $USER:$USER .env.local ``` ### 7.4 Tests de Sécurité à Effectuer ```bash # Test CORS curl -H "Origin: http://evil.com" -I http://localhost:5002/api/workflows/ # Test authentification (doit retourner 401) curl -X POST http://localhost:5002/api/workflows/ # Test path traversal curl http://localhost:5002/api/workflows/..%2F..%2Fetc%2Fpasswd # Test rate limiting (après implémentation) for i in {1..100}; do curl http://localhost:5002/api/workflows/; done ``` --- ## ANNEXES ### A. Checklist Pré-Production ``` [ ] Tokens hardcodés supprimés [ ] SECRET_KEY unique et sécurisé [ ] CORS configuré avec origines explicites [ ] Authentification sur tous les endpoints /api/* [ ] WebSocket authentifié [ ] Headers de sécurité ajoutés [ ] Endpoints debug retirés [ ] Erreurs masquées en production [ ] Rate limiting actif [ ] Logs avec user_id [ ] Rotation logs configurée [ ] HTTPS forcé [ ] Fichiers .env exclus de Git [ ] Permissions fichiers correctes (600) ``` ### B. Contacts & Ressources - OWASP Top 10: https://owasp.org/Top10/ - Flask Security: https://flask.palletsprojects.com/en/2.0.x/security/ - HIPAA Security Rule: https://www.hhs.gov/hipaa/for-professionals/security/ --- **Fin du rapport - À traiter après les démonstrations**