Settings → Wi-Fi: redact password from serial/REPL logs#124
Conversation
Three print sites in the Settings → Wi-Fi app were leaking the
Wi-Fi password to the serial console / REPL:
1. `edit_network_result_callback` — prints `result` which is
`{'result_code': True, 'data': {'ssid': ..., 'password': ...,
'hidden': ...}}`. Fires every time the user saves the
EditNetwork screen.
2. `start_attempt_connecting` — prints `'... SSID 'X' with
password 'Y''`. Fires on every connection attempt.
3. `gotqr_result_callback` — prints the raw result and the raw
QR data. A Wi-Fi QR code's payload is
`WIFI:T:WPA;S:SSID;P:password;H:...;;` — the password is in
plaintext. Fires every time a Wi-Fi QR is scanned.
Discovered while testing LightningPiggy app's Wi-Fi reconnect
flow on a device: the user's home Wi-Fi password was printed to
serial on every connect retry, and would appear in any shared
debug log or REPL paste. Companion to MicroPythonOS#123 (which
fixed the `SharedPreferences.load()` leak in the same vein).
Fix: redact `password` from the result-dict dump, drop the
password argument from the connect-attempt print, and drop both
the full-result and raw-QR prints from the QR callback (replaced
with a minimal status print).
No API change, no behaviour change — only log output.
|
I don't know if this is really needed. Sadly the WiFi password is always accessible in plain text if you have physical access to the ESP. There is IMHO no way to secure this. There is Flash/NVS (Non-Volatile Storage) encryption, but it's not supported by micropython out-of-the-box, i think. |
|
Fair point on flash/NVS — physical access to the chip is a separate threat model that a log-redaction change can't (and isn't trying to) address. Flash encryption would be the right lever there, and you're right that MicroPython doesn't turn it on by default. The vector this PR is closing is different: secrets leaking through logs, not storage. The affected print sites dump the Wi-Fi password to the serial console / REPL on every connect attempt, every EditNetwork save, every Wi-Fi QR scan. That output reaches a much wider audience than anyone with a chip in hand:
I actually spotted this while debugging the LightningPiggyApp with Claude Code — the agent's serial monitor captured my home Wi-Fi password in its transcript on every reconnect. That's the kind of failure mode log-redaction fixes and flash encryption wouldn't touch. The fix is also zero-risk: no API change, no control-flow change, just replacing the leaked field with Happy to discuss further if you'd still rather not take it. |
|
Thanks for both of your thorough considerations, guys! I understand we've reached a loose consensus on the merit of this change so let's merge it! |
Summary
Three
printsites inbuiltin/apps/com.micropythonos.settings.wifi/assets/wifi_settings.pywere dumping the Wi-Fi password to the serial console / REPL on every Wi-Fi interaction:edit_network_result_callback(line 158):resultis{'result_code': True, 'data': {'ssid': '…', 'password': '…', 'hidden': …}}— fires every time the user saves the EditNetwork screen.start_attempt_connecting(line 175):Fires on every connection attempt.
gotqr_result_callback(lines 395 and 398):A Wi-Fi QR code's payload is the standard
WIFI:T:WPA;S:SSID;P:password;H:…;;format — the password is in plaintext. Bothresultanddatacontain it. Fires every time a Wi-Fi QR is scanned.Discovery
Spotted while testing the LightningPiggyApp's Wi-Fi reconnect flow. The device printed the user's real home Wi-Fi password to serial on every connection retry. Same class of leak as #123 (SharedPreferences.load) but at the app layer.
Fix
edit_network_result_callback: shallow-copy the result and replace the nesteddata.passwordwith***before printing.start_attempt_connecting: log only the SSID; drop the password from the print.gotqr_result_callback: replace the two raw-content prints with a minimal status print (justresult_code).All three edits include a comment explaining why so future edits don't accidentally regress.
No behaviour change
CHANGELOG
Added a bullet under the new
Builtin Apps:subsection of the "Future release" block.Release target
Security fix, suggest merging to main for inclusion in the next release regardless of its feature scope. If you'd rather fold it into a patch release, happy to rebase.
Test plan
EditNetwork finished, result: {'result_code': True, 'data': {'ssid': '…', 'password': '***', 'hidden': …}}start_attempt_connecting: Attempting to connect to SSID 'X'with no passwordQR capture finished, result_code=Trueand no rawWIFI:…;P:password;;string🤖 Generated with Claude Code