Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Frameworks:
- AppearanceManager: fix set_light_mode() and set_primary_color() — they called a non-existent `prefs.set_string()` and raised AttributeError for every third-party caller; writes now go through `edit().put_string().commit()` and the LVGL theme is reinitialised when the colour changes
- SharedPreferences: security fix — `load()` no longer prints the entire prefs dict to serial/REPL. Any pref holding a secret (WiFi password in `access_points`, Lightning wallet API keys, NWC secrets, xpubs, etc.) was being leaked to logs every time an app loaded its prefs. Now logs only the filepath and key count

Builtin Apps:
- Settings → Wi-Fi: security fix — password no longer printed to serial/REPL during connection attempts, EditNetwork form returns, or Wi-Fi QR scans. Redacts the three print sites that were leaking the password on every Wi-Fi interaction

OS:
- LilyGo T-Watch S3 Plus: add support for IR Remote app
- Fri3d 2024: add support for IR remote app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,15 @@ def select_ssid_cb(self, ssid):
self.startActivityForResult(intent, self.edit_network_result_callback)

def edit_network_result_callback(self, result):
print(f"EditNetwork finished, result: {result}")
# Redact the password field from the dict dump — `result["data"]`
# contains the WiFi password in plaintext and gets printed to
# serial/REPL every time the user saves an EditNetwork screen.
_redacted = dict(result) if isinstance(result, dict) else result
if isinstance(_redacted, dict) and isinstance(_redacted.get("data"), dict):
_redacted["data"] = dict(_redacted["data"])
if "password" in _redacted["data"]:
_redacted["data"]["password"] = "***"
print(f"EditNetwork finished, result: {_redacted}")
if result.get("result_code") is True:
data = result.get("data")
if data:
Expand All @@ -172,7 +180,9 @@ def edit_network_result_callback(self, result):
self.start_attempt_connecting(ssid, password)

def start_attempt_connecting(self, ssid, password):
print(f"start_attempt_connecting: Attempting to connect to SSID '{ssid}' with password '{password}'")
# Log only the SSID — the password is sensitive and was being
# printed to serial/REPL on every connect attempt.
print(f"start_attempt_connecting: Attempting to connect to SSID '{ssid}'")
self.scan_button.add_state(lv.STATE.DISABLED)
self.scan_button_label.set_text("Connecting...")
if self.busy_connecting:
Expand Down Expand Up @@ -382,10 +392,14 @@ def forget_cb(self, event):
self.startActivityForResult(Intent(activity_class=CameraActivity).putExtra("scanqr_intent", True), self.gotqr_result_callback)

def gotqr_result_callback(self, result):
print(f"QR capture finished, result: {result}")
# Don't print the raw result — a WiFi QR code's payload
# (`WIFI:T:...;S:SSID;P:password;H:...;;`) contains the password
# in plaintext and this runs every time a QR is scanned.
print("QR capture finished, result_code={}".format(
result.get("result_code") if isinstance(result, dict) else None))
if result.get("result_code"):
data = result.get("data")
print(f"Setting textarea data: {data}")
# Not logging `data` either — same reason: it's the raw QR.
authentication_type, ssid, password, hidden = self.decode_wifi_qr_code(data)
if ssid and self.ssid_ta: # not always present
self.ssid_ta.set_text(ssid)
Expand Down
Loading