From 1d4fd09444bfad0d765342e3a493026c0706cbcb Mon Sep 17 00:00:00 2001 From: sebingel Date: Mon, 6 Apr 2026 07:48:59 +0000 Subject: [PATCH] Fix robustness issues in Fritz!Box plugin before PR Two independent reliability problems were identified during PR readiness review. First, FritzConnection had no explicit timeout, meaning an unreachable or slow Fritz!Box would block the plugin process indefinitely until the OS TCP timeout fired (typically 2+ minutes), making the 60s RUN_TIMEOUT in config.json ineffective. Second, hashlib.md5() called without usedforsecurity=False raises ValueError on FIPS-enforced systems (common in enterprise Docker hosts), silently breaking the guest WiFi synthetic device feature for those users. Changes: - Add timeout=10 to FritzConnection(...) call (fritzbox.py:57) The fritzconnection library accepts a timeout parameter directly in __init__; it applies per individual HTTP request to the Fritz!Box, bounding each TR-064 call including the initial connection handshake. - Add usedforsecurity=False to hashlib.md5() call (fritzbox.py:191) The MD5 hash is used only for deterministic MAC derivation (not for any security purpose), so the flag is semantically correct and lifts the FIPS restriction without changing the computed value. - Update test assertion to include timeout=10 (test_fritzbox.py:307) assert_called_once_with checks the exact call signature; the test expectation must match the updated production code. The plugin now fails fast on unreachable Fritz!Box (within 10s per request) and works correctly on FIPS-enabled hosts. Default behavior for standard deployments is unchanged. --- front/plugins/fritzbox/fritzbox.py | 3 ++- test/plugins/test_fritzbox.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/front/plugins/fritzbox/fritzbox.py b/front/plugins/fritzbox/fritzbox.py index 08915ecb..af6b2fca 100755 --- a/front/plugins/fritzbox/fritzbox.py +++ b/front/plugins/fritzbox/fritzbox.py @@ -54,6 +54,7 @@ def get_fritzbox_connection(host, port, user, password, use_tls): user=user, password=password, use_tls=use_tls, + timeout=10, ) mylog('verbose', [f'[{pluginName}] Successfully connected to Fritz!Box']) @@ -188,7 +189,7 @@ def create_guest_wifi_device(fc): # The 02 prefix sets the locally-administered bit, ensuring no collision # with real OUI-assigned MACs. The remaining 5 bytes come from an MD5 # hash of the Fritz!Box MAC so the guest MAC is stable across runs. - digest = hashlib.md5(f'GUEST:{normalize_mac(fritzbox_mac)}'.encode()).digest() + digest = hashlib.md5(f'GUEST:{normalize_mac(fritzbox_mac)}'.encode(), usedforsecurity=False).digest() guest_mac = '02:' + ':'.join(f'{b:02x}' for b in digest[:5]) else: # Fallback if we can't get Fritz!Box MAC diff --git a/test/plugins/test_fritzbox.py b/test/plugins/test_fritzbox.py index 4a1d13a8..cddb2cea 100644 --- a/test/plugins/test_fritzbox.py +++ b/test/plugins/test_fritzbox.py @@ -304,7 +304,7 @@ class TestGetFritzboxConnection: assert result is fc_instance fc_class.assert_called_once_with( - address="fritz.box", port=49443, user="admin", password="pass", use_tls=True, + address="fritz.box", port=49443, user="admin", password="pass", use_tls=True, timeout=10, ) def test_import_error_returns_none(self):