java-topology/defects/zephyr-0001/test/ZephyrWifiCredShellTest.java
russell@unturf.com 1e10775b90 jitsi-videobridge: 3 CWE-407 defects, MOADs 0002-0005 CLEAN; woodpecker: 1 CWE-407 + 1 CWE-312, MOADs 0002/0003/0005 CLEAN
jitsi-videobridge (Kotlin/Java video conferencing bridge):
- 0001: Prioritize.kt selectedSourceNames.contains()+indexOf() inside forEach over conferenceSources, O(C*S)
- 0002: BandwidthAllocator.kt selectedSources getter List.contains() dedup inside forEach, O(S^2)
- 0003: ConferenceSpeechActivity.java endpointsChanged() ArrayList.contains() in removeIf+for loop, O(E^2)
  Fix: HashSet for O(1) membership; pre-built index map for indexOf
  Unit test: 4/4 PASS, 19-35x op-count reduction at N=200

woodpecker-0001 (Go CI/CD pipeline step builder):
- filterItemsWithMissingDependencies() calls containsItemWithName() (O(N) linear scan) inside
  two nested loops over items and deps: O(N*D*N) = O(N^2)
  Fix: pre-build name-set map for O(1) lookup, O(N) total
  Unit test: 3/3 PASS, 20x op-count reduction at N=100

woodpecker-0002 (CWE-312 credential logging):
- shared/token/token.go ParseRequest() logs raw Authorization header value at Trace level:
  log.Trace().Msgf("token.ParseRequest: found token in header: %s", token)
  Exposes full Bearer JWT token in application logs
  Fix: log only that header was found, not its value
  Unit test: 3/3 PASS
2026-03-31 20:18:44 -04:00

187 lines
8.3 KiB
Java

import java.util.*;
/**
* Unit test for zephyr-0001: wifi_credentials_shell.c print_network_info()
* prints WiFi PSK and EAP-TLS key_passwd verbatim to the shell (CWE-312).
*
* Models the C pattern in print_network_info():
*
* shell_fprintf(sh, ..., ", password: \"%.*s\", password_len: %d",
* (int)creds.password_len, creds.password, creds.password_len);
*
* When a user runs "wifi cred list" on a Zephyr shell, all stored network
* credentials including WPA2-PSK passwords and EAP-TLS private-key passphrases
* are printed in cleartext. On serial/UART consoles this is visible to anyone
* with physical access; logging backends may persist the secret.
*
* Fix: replace the credential value with "[redacted]", keep the length.
*/
public class ZephyrWifiCredShellTest {
static final String REDACTED = "[redacted]";
// Security type constants (mirroring Zephyr wifi_security_type)
static final int WIFI_SECURITY_TYPE_NONE = 0;
static final int WIFI_SECURITY_TYPE_PSK = 1;
static final int WIFI_SECURITY_TYPE_PSK_SHA256 = 2;
static final int WIFI_SECURITY_TYPE_SAE = 3;
static final int WIFI_SECURITY_TYPE_WPA_PSK = 9;
static final int WIFI_SECURITY_TYPE_EAP_TLS = 7;
// --- Defective version: prints password verbatim ---
static String printNetworkInfoDefective(String ssid, int secType,
String password, String keyPasswd) {
StringBuilder sb = new StringBuilder();
sb.append(String.format(" network ssid: \"%s\", ssid_len: %d, type: %d",
ssid, ssid.length(), secType));
if (secType == WIFI_SECURITY_TYPE_PSK ||
secType == WIFI_SECURITY_TYPE_PSK_SHA256 ||
secType == WIFI_SECURITY_TYPE_SAE ||
secType == WIFI_SECURITY_TYPE_WPA_PSK) {
// DEFECT: password value logged verbatim
sb.append(String.format(", password: \"%s\", password_len: %d",
password, password.length()));
}
if (secType == WIFI_SECURITY_TYPE_EAP_TLS && keyPasswd != null && !keyPasswd.isEmpty()) {
// DEFECT: key_passwd value logged verbatim
sb.append(String.format(", key_passwd: \"%s\", key_passwd_len: %d",
keyPasswd, keyPasswd.length()));
}
return sb.toString();
}
// --- Fixed version: redacts password and key_passwd ---
static String printNetworkInfoFixed(String ssid, int secType,
String password, String keyPasswd) {
StringBuilder sb = new StringBuilder();
sb.append(String.format(" network ssid: \"%s\", ssid_len: %d, type: %d",
ssid, ssid.length(), secType));
if (secType == WIFI_SECURITY_TYPE_PSK ||
secType == WIFI_SECURITY_TYPE_PSK_SHA256 ||
secType == WIFI_SECURITY_TYPE_SAE ||
secType == WIFI_SECURITY_TYPE_WPA_PSK) {
// FIX: redact password value, keep length
sb.append(String.format(", password: %s, password_len: %d",
REDACTED, password.length()));
}
if (secType == WIFI_SECURITY_TYPE_EAP_TLS && keyPasswd != null && !keyPasswd.isEmpty()) {
// FIX: redact key_passwd value, keep length
sb.append(String.format(", key_passwd: %s, key_passwd_len: %d",
REDACTED, keyPasswd.length()));
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println("=== zephyr-0001: wifi_credentials_shell PSK/key_passwd CWE-312 ===\n");
int pass = 0, total = 0;
// Test 1: WPA2-PSK defective path leaks password
{
total++;
String psk = "SuperSecretWifi123!";
String out = printNetworkInfoDefective("HomeNetwork", WIFI_SECURITY_TYPE_PSK, psk, null);
boolean leaks = out.contains(psk);
assert leaks : "FAIL T1: expected defective path to contain PSK";
System.out.println("T1 CONFIRMED defective: PSK in output = " + leaks + " out=" + out);
pass++;
}
// Test 2: WPA2-PSK fixed path redacts password
{
total++;
String psk = "SuperSecretWifi123!";
String out = printNetworkInfoFixed("HomeNetwork", WIFI_SECURITY_TYPE_PSK, psk, null);
boolean hidden = !out.contains(psk);
boolean hasRedacted = out.contains(REDACTED);
boolean hasLen = out.contains(String.valueOf(psk.length()));
assert hidden : "FAIL T2: fixed path should not contain PSK";
assert hasRedacted : "FAIL T2: fixed path should contain [redacted]";
assert hasLen : "FAIL T2: fixed path should still show password_len";
System.out.printf("T2 PASS fixed: hidden=%b redacted=%b len_present=%b%n",
hidden, hasRedacted, hasLen);
pass++;
}
// Test 3: SAE (WPA3) password redacted
{
total++;
String saePass = "WPA3SensitivePass";
String out = printNetworkInfoFixed("Office5G", WIFI_SECURITY_TYPE_SAE, saePass, null);
assert !out.contains(saePass) : "FAIL T3: SAE password should be redacted";
assert out.contains(REDACTED) : "FAIL T3: [redacted] marker expected";
System.out.println("T3 PASS: SAE password redacted correctly");
pass++;
}
// Test 4: EAP-TLS key_passwd defective path leaks passphrase
{
total++;
String keyPass = "PrivKeyPassphrase42";
String out = printNetworkInfoDefective("EnterpriseNet", WIFI_SECURITY_TYPE_EAP_TLS, "", keyPass);
boolean leaks = out.contains(keyPass);
assert leaks : "FAIL T4: expected defective EAP-TLS path to contain key_passwd";
System.out.println("T4 CONFIRMED defective: EAP key_passwd in output = " + leaks);
pass++;
}
// Test 5: EAP-TLS key_passwd fixed path redacts passphrase
{
total++;
String keyPass = "PrivKeyPassphrase42";
String out = printNetworkInfoFixed("EnterpriseNet", WIFI_SECURITY_TYPE_EAP_TLS, "", keyPass);
boolean hidden = !out.contains(keyPass);
boolean hasRedacted = out.contains(REDACTED);
assert hidden : "FAIL T5: fixed EAP-TLS path should not contain key_passwd";
assert hasRedacted : "FAIL T5: [redacted] expected in EAP-TLS output";
System.out.printf("T5 PASS: EAP key_passwd hidden=%b redacted=%b%n", hidden, hasRedacted);
pass++;
}
// Test 6: OPEN network (no password) - no redacted marker, no password field
{
total++;
String out = printNetworkInfoFixed("PublicWifi", WIFI_SECURITY_TYPE_NONE, "", null);
boolean noPassword = !out.contains("password:");
assert noPassword : "FAIL T6: OPEN network should not have password field";
System.out.println("T6 PASS: OPEN network - no password field in output");
pass++;
}
// Test 7: SSID is still shown (not a secret)
{
total++;
String ssid = "MyHomeNetwork";
String psk = "secret123";
String out = printNetworkInfoFixed(ssid, WIFI_SECURITY_TYPE_PSK, psk, null);
assert out.contains(ssid) : "FAIL T7: SSID should still be visible";
assert !out.contains(psk) : "FAIL T7: PSK should be redacted";
assert out.contains(REDACTED) : "FAIL T7: [redacted] expected";
System.out.println("T7 PASS: SSID visible, PSK redacted");
pass++;
}
// Test 8: WPA-PSK (legacy) also redacted
{
total++;
String psk = "OldSchoolPass";
String out = printNetworkInfoFixed("LegacyAP", WIFI_SECURITY_TYPE_WPA_PSK, psk, null);
assert !out.contains(psk) : "FAIL T8: WPA-PSK password should be redacted";
assert out.contains(REDACTED) : "FAIL T8: [redacted] expected for WPA-PSK";
System.out.println("T8 PASS: WPA-PSK (legacy) password redacted");
pass++;
}
System.out.printf("%n%d/%d tests PASS%n", pass, total);
if (pass != total) {
System.exit(1);
}
}
}