import java.util.ArrayList; import java.util.List; /** * Test for esp-idf-0001: CWE-312 WiFi password logged verbatim via ESP_LOGD * in components/esp_wifi/src/smartconfig.c handler_got_ssid_passwd(). * * Pattern: * ESP_LOGD(TAG, "PASSWORD:%s", password) * * When debug logging is enabled the WiFi PSK (pre-shared key) is emitted * verbatim to serial/JTAG output. Any listener on those interfaces obtains * the plaintext credential without any further effort. * * Fix: remove the ESP_LOGD("PASSWORD:%s", ...) line. SSID logging (non-secret) * is acceptable; PSK logging is not. * * Compile and run (no build tool required): * javac defects/esp-idf-0001/test/EspIdf0001Test.java -d /tmp/esp-idf-0001 * java -cp /tmp/esp-idf-0001 EspIdf0001Test */ public class EspIdf0001Test { private static int passed = 0; private static int failed = 0; // --- Simulated log collector --- static class LogCollector { private final List lines = new ArrayList<>(); void logd(String tag, String fmt, Object... args) { lines.add(String.format(fmt, args)); } boolean containsText(String text) { for (String line : lines) { if (line.contains(text)) return true; } return false; } int size() { return lines.size(); } } // --- Defective: logs password in DEBUG output --- static void handleGotSsidPasswdDefective(String ssid, String password, LogCollector log) { log.logd("smartconfig", "SSID:%s", ssid); log.logd("smartconfig", "PASSWORD:%s", password); // CWE-312 site log.logd("smartconfig", "Phone ip: 192.168.1.1"); } // --- Fixed: password line removed --- static void handleGotSsidPasswdFixed(String ssid, String password, LogCollector log) { log.logd("smartconfig", "SSID:%s", ssid); // PASSWORD log line removed — fix for esp-idf-0001 log.logd("smartconfig", "Phone ip: 192.168.1.1"); } // --- Tests --- static void testDefectiveLogsPassword() { LogCollector log = new LogCollector(); String password = "MySecretWiFiPSK123"; handleGotSsidPasswdDefective("MyNet", password, log); check("defective must log the password (confirms CWE-312 site is present)", log.containsText(password)); } static void testFixedDoesNotLogPassword() { LogCollector log = new LogCollector(); String password = "MySecretWiFiPSK123"; handleGotSsidPasswdFixed("MyNet", password, log); check("fixed must NOT log the WiFi PSK in any log line", !log.containsText(password)); } static void testFixedStillLogsSsid() { LogCollector log = new LogCollector(); handleGotSsidPasswdFixed("HomeNetwork_5GHz", "secret", log); check("SSID (non-sensitive) must still appear in logs after fix", log.containsText("HomeNetwork_5GHz")); } static void testFixedHasFewerLines() { LogCollector defLog = new LogCollector(); LogCollector fixLog = new LogCollector(); handleGotSsidPasswdDefective("net", "pw", defLog); handleGotSsidPasswdFixed("net", "pw", fixLog); check("fixed version produces fewer log lines than defective", fixLog.size() < defLog.size()); } static void testPasswordNotLeakedAcrossMultipleCalls() { // Simulate multiple smartconfig events — none should leak password String[] passwords = {"PSK-alpha", "PSK-beta", "PSK-gamma"}; for (String pw : passwords) { LogCollector log = new LogCollector(); handleGotSsidPasswdFixed("net", pw, log); check("password '" + pw + "' must not appear in any log line", !log.containsText(pw)); } } // --- Harness --- static void check(String desc, boolean cond) { if (cond) { System.out.println(" PASS: " + desc); passed++; } else { System.out.println(" FAIL: " + desc); failed++; } } public static void main(String[] args) { System.out.println("=== EspIdf0001Test (CWE-312 WiFi PSK logged) ===\n"); testDefectiveLogsPassword(); testFixedDoesNotLogPassword(); testFixedStillLogsSsid(); testFixedHasFewerLines(); testPasswordNotLeakedAcrossMultipleCalls(); System.out.println("\n--- " + passed + " passed, " + failed + " failed ---"); if (failed > 0) System.exit(1); } }