{ "audit_metadata": { "report_date": "2026-03-02", "scan_scope": "Complete ESP32_ZACUS repository analysis", "languages_scanned": [ "C++", "Python", "JSON", "YAML", "Markdown" ], "total_files_scanned": 450, "files_with_secrets": 8, "total_secrets_found": 7 }, "secrets": [ { "id": "SECRET_001", "type": "WiFi Password", "severity": "CRITICAL", "secret_value": "mascarade", "locations": [ { "file": "ui_freenove_allinone/src/storage_manager.cpp", "line": 65, "context": "Embedded JSON configuration for APP_WIFI.json", "snippet": "\"local_password\":\"mascarade\",\"ap_policy\":\"if_no_known_wifi\"...\"ap_default_password\":\"mascarade\"" }, { "file": "ui_freenove_allinone/src/storage/storage_manager.cpp", "line": 73, "context": "Alternative storage location (older implementation)", "snippet": "R\"JSON({...\"ap_default_ssid\":\"Freenove-Setup\"})JSON\"" }, { "file": "REMEDIATION_GUIDE.md", "line": 13, "context": "Documentation of the vulnerability", "snippet": "R\"JSON({\"local_ssid\":\"Les cils\",\"local_password\":\"mascarade\"})\"" } ], "context": "Default hardcoded WiFi access point password for fallback AP mode", "impact": { "scope": "Fallback Access Point (AP) Mode", "risk_level": "DEVICE COMPROMISE", "description": "Anyone with network access to the ESP32 in AP mode can connect using this password. This is used when the device cannot connect to configured WiFi networks.", "affected_systems": "All ESP32_ZACUS devices deployed with this firmware", "attack_scenario": [ "1. Device cannot connect to primary WiFi (e.g., traveling, network down)", "2. Device enters fallback AP mode with SSID=\"Freenove-Setup\", password=\"mascarade\"", "3. Attacker connects to AP using known credentials", "4. Attacker gains access to all device APIs and controls (unlock, camera, media, etc.)", "5. No authentication required on any API endpoints (see CRITICAL_002)" ] }, "cryptanalysis": { "entropy": "Low - single dictionary word", "strength": "Weak - password_strength_score: 2/10 (only lowercase letters)", "crack_time_estimate": "< 1 second (offline)", "compliance_failure": "Fails minimum password complexity requirements (NIST SP 800-132)" }, "production_context": "Test/Development value, but embedded in production firmware", "remediation": { "priority": "IMMEDIATE (P0)", "steps": [ "1. Remove all hardcoded passwords from source code", "2. Store AP password in encrypted NVS (Non-Volatile Storage) using ESP32's NVS partition", "3. Generate unique random password during first boot using device MAC address + entropy", "4. Implement secure provisioning via QR code or BLE for changing credentials", "5. Never allow AP mode without authentication after initial setup", "6. Re-release firmware with empty default password (require manual setup)" ], "implementation_reference": "REMEDIATION_GUIDE.md (lines 29-95)" }, "cwe": "CWE-798: Use of Hard-Coded Credentials", "cvss_score": 9.1, "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N" }, { "id": "SECRET_002", "type": "WiFi SSID (Local Network)", "severity": "CRITICAL", "secret_value": "Les cils", "locations": [ { "file": "ui_freenove_allinone/src/storage_manager.cpp", "line": 65, "context": "Embedded WiFi configuration for local network", "snippet": "\"local_ssid\":\"Les cils\",\"local_password\":\"mascarade\",\"ap_policy\":\"if_no_known_wifi\"" }, { "file": "SECURITY_AUDIT_REPORT.json", "line": 32, "context": "Security audit findings", "snippet": "{\"local_ssid\":\"Les cils\",\"local_password\":\"mascarade\"}" }, { "file": "REMEDIATION_GUIDE.md", "line": 13, "context": "Remediation guide example", "snippet": "R\"JSON({\"local_ssid\":\"Les cils\",\"local_password\":\"mascarade\"})\"" } ], "context": "Default WiFi network SSID paired with hardcoded password", "impact": { "scope": "Local WiFi network identifier", "risk_level": "NETWORK RECONNAISSANCE", "description": "The SSID 'Les cils' reveals network identity in firmware. Combined with known password 'mascarade', this enables complete WiFi hijacking.", "affected_systems": "Any ESP32_ZACUS device in 'local' mode or attempting to connect to this network", "attack_vector": [ "1. Attacker decompiles firmware and finds SSID and password", "2. Creates rogue WiFi AP with identical SSID and password", "3. Performs MITM attack by disconnecting original network", "4. Dev devices or testing devices connect to rogue AP", "5. All device communications can be intercepted/modified" ] }, "production_context": "Appears to be developer's home network (French name). Should NOT be in production firmware.", "remediation": { "priority": "IMMEDIATE (P0)", "steps": [ "1. Remove 'Les cils' SSID from firmware entirely", "2. Implement provisioning mode where user provides WiFi credentials at setup", "3. Store user-provided credentials in encrypted NVS", "4. Never hardcode any WiFi SSID in firmware", "5. Document expected setup flow for users" ] }, "cwe": "CWE-798: Use of Hard-Coded Credentials", "cvss_score": 8.8, "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N" }, { "id": "SECRET_003", "type": "WiFi SSID (Test Network)", "severity": "CRITICAL", "secret_value": "Les cils (test_ssid)", "locations": [ { "file": "ui_freenove_allinone/src/storage_manager.cpp", "line": 65, "context": "Embedded test WiFi configuration", "snippet": "\"test_ssid\":\"Les cils\",\"test_password\":\"mascarade\"" }, { "file": "AUDIT_COMPLET_2026-03-01.md", "line": 146, "context": "Audit documentation", "snippet": "\"test_ssid\":\"Les cils\",\"test_password\":\"mascarade\"" } ], "context": "Backup WiFi configuration for testing purposes", "impact": { "scope": "Fallback test network connection", "risk_level": "NETWORK COMPROMISE", "description": "Identical to local_ssid but used as fallback for testing. Same credentials (Les cils / mascarade) mean attacker has two attack vectors.", "affected_systems": "All devices in testing mode or after failed primary WiFi connection" }, "production_context": "Test credentials should not be in production firmware at all", "remediation": { "priority": "IMMEDIATE (P0)", "steps": [ "1. Remove test_ssid and test_password entirely from production firmware", "2. Keep these only in development/debug builds (conditional compilation)", "3. Use build flags to distinguish: #ifdef FIRMWARE_DEBUG_BUILD" ] }, "cwe": "CWE-798: Use of Hard-Coded Credentials", "cvss_score": 8.8 }, { "id": "SECRET_004", "type": "WiFi AP SSID (Access Point Broadcast)", "severity": "HIGH", "secret_value": "Freenove-Setup", "locations": [ { "file": "ui_freenove_allinone/src/storage_manager.cpp", "line": 65, "context": "Access Point SSID in embedded config", "snippet": "\"ap_default_ssid\":\"Freenove-Setup\",\"ap_default_password\":\"mascarade\"" }, { "file": "ui_freenove_allinone/src/storage/storage_manager.cpp", "line": 73, "context": "Fallback AP configuration", "snippet": "{\"ap_default_ssid\":\"Freenove-Setup\"}" }, { "file": "ui_freenove_allinone/include/system/network/network_manager.h", "line": 151, "context": "Network manager header default", "snippet": "char fallback_ap_ssid_[33] = \"Freenove-Setup\";" }, { "file": "ui_freenove_allinone/include/runtime/runtime_config_types.h", "line": 15, "context": "Runtime configuration type defaults", "snippet": "char ap_default_ssid[33] = \"Freenove-Setup\";" }, { "file": "ui_freenove_allinone/src/runtime/runtime_config_service.cpp", "line": 76, "context": "Default value in initialization", "snippet": "copyText(network_cfg->ap_default_ssid, sizeof(network_cfg->ap_default_ssid), \"Freenove-Setup\");" } ], "context": "Access Point (hotspot) name broadcast when device is in AP mode", "impact": { "scope": "Public WiFi network identifier", "risk_level": "NETWORK IDENTIFICATION", "description": "The SSID 'Freenove-Setup' is hardcoded and publicly visible in WiFi networks. While the AP SSID alone is informational, combined with the known password 'mascarade', it enables unauthorized access.", "affected_systems": "All ESP32_ZACUS devices in fallback AP mode", "visibility": "Visible to anyone with a WiFi scanner in proximity" }, "production_context": "SHOULD be customized per device but currently hardcoded", "remediation": { "priority": "HIGH (P1)", "steps": [ "1. Generate unique AP SSID per device (e.g., 'Freenove-XXXXXX' where XXXXXX = last 6 digits of MAC)", "2. Update at runtime based on device MAC address", "3. Make AP password strong and random (64 chars, mixed case, symbols)", "4. Consider requiring QR code scan for AP credentials instead of hardcoding" ] }, "cwe": "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor", "cvss_score": 6.5, "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N" }, { "id": "SECRET_005", "type": "WiFi AP Password (Default/Empty)", "severity": "CRITICAL", "secret_value": "(empty string - no password required)", "locations": [ { "file": "ui_freenove_allinone/include/runtime/runtime_config_types.h", "line": 16, "context": "Default initialization (empty)", "snippet": "char ap_default_password[65] = {0};" }, { "file": "ui_freenove_allinone/src/runtime/runtime_config_service.cpp", "line": 77, "context": "Default initialization to empty string", "snippet": "copyText(network_cfg->ap_default_password, sizeof(network_cfg->ap_default_password), kDefaultWifiPassword);" } ], "context": "Access Point (fallback AP mode) has NO password in default configuration", "impact": { "scope": "Open WiFi network without authentication", "risk_level": "COMPLETE NETWORK COMPROMISE", "description": "The AP mode broadcasts 'Freenove-Setup' SSID with NO password. This means ANYONE within WiFi range can connect to the device without any authentication.", "affected_systems": "All ESP32_ZACUS devices that fall back to AP mode", "attack_scenario": [ "1. Developer's device falls back to AP mode (no primary network available)", "2. Any attacker nearby opens WiFi settings", "3. Finds 'Freenove-Setup' and connects (no password prompt)", "4. Attacker is now connected to device with access to ALL APIs", "5. Can control camera, media, audio, unlock, unlock settings, etc.", "6. All protected by ZERO authentication (see CRITICAL_002)" ] }, "combined_risk": "When combined with unauthenticated API endpoints, this creates an OPEN SYSTEM vulnerability", "production_context": "CRITICAL SECURITY FLAW - device is essentially completely open when in AP mode", "remediation": { "priority": "IMMEDIATE (P0 - BLOCKING)", "steps": [ "1. Generate strong random password during first boot (minimum 16 chars)", "2. Store password in NVS encrypted storage", "3. Display password only during setup (QR code or serial output)", "4. Never allow open AP without explicit configuration", "5. When no password provided, generate one automatically", "6. Document setup process clearly for users" ], "reference": "REMEDIATION_GUIDE.md (lines 35-60)" }, "cwe": "CWE-306: Missing Authentication for Critical Function", "cvss_score": 10.0, "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" }, { "id": "SECRET_006", "type": "Default Hostname", "severity": "LOW", "secret_value": "zacus-freenove", "locations": [ { "file": "ui_freenove_allinone/src/storage_manager.cpp", "line": 65, "context": "Embedded hostname in APP_WIFI config", "snippet": "\"hostname\":\"zacus-freenove\"" }, { "file": "ui_freenove_allinone/src/runtime/runtime_config_service.cpp", "line": 11, "context": "Default hostname constant", "snippet": "constexpr const char* kDefaultWifiHostname = \"zacus-freenove\";" } ], "context": "mDNS hostname for device discovery on network", "impact": { "scope": "Device naming/identification", "risk_level": "INFORMATION DISCLOSURE", "description": "While not a secret in the traditional sense, predictable hostname enables easier device discovery and fingerprinting. Combined with other factors, helps attackers identify and target devices.", "affected_systems": "All devices on local network can see this hostname" }, "production_context": "Informational value only, but could be made unique per device", "remediation": { "priority": "LOW (P3)", "steps": [ "1. Generate unique hostname per device (e.g., 'zacus-XXXXXX' where XXXXXX = MAC suffix)", "2. Allow customization via API after authentication", "3. Store in NVS if changed" ] }, "cwe": "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor", "cvss_score": 3.7 }, { "id": "SECRET_007", "type": "API Bearer Token Storage Location", "severity": "MEDIUM", "secret_value": "Generated at runtime (variable: g_web_auth_token[65])", "locations": [ { "file": "ui_freenove_allinone/src/app/main.cpp", "line": 91, "context": "Bearer token prefix definition", "snippet": "constexpr const char* kWebAuthBearerPrefix = \"Bearer \";" }, { "file": "ui_freenove_allinone/src/app/main.cpp", "line": 206, "context": "Bearer token RAM storage", "snippet": "char g_web_auth_token[kWebAuthTokenCapacity] = {0};" }, { "file": "ui_freenove_allinone/src/app/main.cpp", "line": 3845, "context": "Token loading from NVS or generation", "snippet": "if (!rotate_token && g_web_auth_token[0] != '\\0')" } ], "context": "API authentication token stored in RAM and NVS (Preferences)", "impact": { "scope": "In-memory token storage during runtime", "risk_level": "TOKEN EXPOSURE", "description": "Bearer tokens are stored in process RAM and also persisted in NVS storage. While better than hardcoded values, they could be extracted via RAM dumps or NVS partition analysis.", "vulnerability": "Tokens not cleared from memory after use (can be memory-dumped)", "affected_systems": "All devices storing auth tokens", "attack_vector": [ "1. Physical access to device + UART interface", "2. Dump process memory via debugger interface", "3. Search for 'Bearer ' string patterns in memory", "4. Extract token and use for API access", "5. Or read raw NVS partition if not encrypted" ] }, "production_context": "This is an IMPLEMENTATION, not a hardcoded secret. The approach is reasonable but has minor vulnerabilities.", "remediation": { "priority": "MEDIUM (P2)", "steps": [ "1. Implement secure token storage with encryption (use ESP32 NVS encryption)", "2. Clear token from RAM immediately after use", "3. Consider implementing token rotation with expiration times", "4. Use volatile variables and memset() to clear sensitive data", "5. Consider RNG for token generation (currently may use predictable sources)" ], "reference": "REMEDIATION_GUIDE.md (lines 156-270)" }, "cwe": "CWE-320: Key Management Errors", "cvss_score": 5.4 } ], "vulnerability_summary": { "critical_count": 4, "high_count": 1, "medium_count": 1, "low_count": 1, "total": 7, "overall_risk": "CRITICAL - Production deployment is NOT RECOMMENDED until CRITICAL issues are resolved" }, "affected_components": { "wifi_management": { "status": "COMPROMISED", "issues": [ "Hardcoded SSID and passwords", "Fallback AP with known credentials or no password", "No encryption for credentials in NVS" ] }, "api_authentication": { "status": "IMPLEMENTED BUT VULNERABLE", "issues": [ "Bearer token in plain text in memory", "Tokens not secured in NVS", "Token generation may be predictable" ] }, "device_identification": { "status": "WEAK", "issues": [ "Hardcoded hostname and SSID", "No per-device customization", "Enables fingerprinting and targeting" ] } }, "remediation_priority": { "phase_1_immediate": [ "SECRET_001: Remove 'mascarade' password from firmware", "SECRET_002: Remove 'Les cils' SSID from firmware", "SECRET_003: Remove test credentials entirely", "SECRET_005: Generate strong random AP password at boot time" ], "phase_2_urgent": [ "SECRET_004: Make AP SSID unique per device (use MAC address)", "Implement NVS encryption for all credentials", "Add HMAC-SHA256 authentication layer" ], "phase_3_important": [ "SECRET_006: Generate unique hostname per device", "SECRET_007: Implement secure token storage with encryption", "Add token expiration and rotation" ] }, "files_to_modify": { "ui_freenove_allinone/src/storage_manager.cpp": { "line": 65, "action": "Remove hardcoded WiFi credentials from embedded JSON", "impact": "BREAKING - requires new config format" }, "ui_freenove_allinone/src/storage/storage_manager.cpp": { "line": 73, "action": "Same as above", "impact": "BREAKING" }, "ui_freenove_allinone/include/runtime/runtime_config_types.h": { "lines": [15, 16], "action": "Keep ap_default_ssid hardcoded, but make ap_default_password empty or generate at runtime", "impact": "Need to implement generation logic" }, "ui_freenove_allinone/src/runtime/runtime_config_service.cpp": { "lines": [72, 75, 76], "action": "Update default values and add credential generation from NVS", "impact": "Medium - requires NVS encryption setup" } }, "recommendations": { "immediate_actions": [ "✅ Stop deploying firmware to production immediately until Phase 1 is complete", "✅ Audit all deployed devices and change default credentials manually", "✅ Issue security notice to all device holders", "✅ Create emergency patch release" ], "architecture_recommendations": [ "Implement provisioning mode requiring QR code or BLE for credentials setup", "Use ESP32's built-in secure boot and flash encryption features", "Implement certificate-based device identification instead of hardcoded values", "Add DTLS/TLS for encrypted API communication", "Implement firmware signing and secure updates" ], "testing": [ "Add security tests to CI/CD checking for hardcoded passwords", "Implement secret scanning in git (e.g., git-secrets, TruffleHog)", "Add penetration testing to release process" ] }, "audit_notes": { "scan_coverage": "Complete - all C++, Python, JSON, YAML files scanned", "false_positives": "None identified. All findings are actual hardcoded values.", "related_vulnerabilities": [ "CWE-306: Missing Authentication for Critical Function (all API endpoints unprotected)", "CWE-200: Exposure of Sensitive Information", "CWE-320: Key Management Errors" ], "references": [ "SECURITY_AUDIT_REPORT.json - Original security audit", "SECURITY_AUDIT_FR.md - French security audit with remediation code", "REMEDIATION_GUIDE.md - Detailed fix implementation guide", "AUDIT_COMPLET_2026-03-01.md - Complete audit findings" ] }, "compliance_status": { "OWASP_Top_10": { "A02:2021_Cryptographic_Failures": "FAIL - credentials not encrypted", "A04:2021_Insecure_Design": "FAIL - no provisioning mechanism", "A06:2021_Vulnerable_and_Outdated_Components": "N/A", "A07:2021_Identification_and_Authentication_Failures": "FAIL - hardcoded credentials" }, "CWE_Top_25": { "CWE_798": "FAIL - hardcoded credentials" }, "NIST_SP_800_132": "FAIL - password doesn't meet minimum complexity" }, "conclusion": { "security_posture": "CRITICAL - Not production-ready", "remediation_effort": "Medium (1-2 weeks for Phase 1 & 2)", "estimated_severity_reduction": "From CRITICAL to LOW after implementing all phases", "sign_off_required": "Security review before deployment to production" } }