fix(satellite): Geheimnisse aus FritzBox-Antworten erreichen ARIA nicht

Lesende TR-064-Aktionen geben teils Geheimnisse zurueck (GetSecurityKeys →
WLAN-Schluessel, Kennwoerter, PINs). Die gingen bisher im Ergebnis an ARIA
und damit ans Sprachmodell. Felder mit Passphrase/Password/PreSharedKey/
WEPKey/Secret/PIN werden jetzt als '•••• (verborgen)' geliefert. Schickt
ARIA den Platzhalter in einer Set-Aktion zurueck, lehnt der Satellit ab —
sonst setzte die Box ihn als neuen Schluessel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 17:43:04 +01:00
co-authored by Claude Opus 5.5
parent c545a1cd77
commit 5af03eedb9
+16 -1
View File
@@ -1404,6 +1404,13 @@ def _fb_call(ip: str, user: str, pw: str, params: dict) -> dict:
"erneut mit confirmed=true aufrufen.")}
args = params.get("args") if isinstance(params.get("args"), dict) else {}
args = {(k if k.startswith("New") else "New" + k): v for k, v in args.items()}
hidden = [k for k, v in args.items() if "(verborgen)" in str(v)]
if hidden:
# Sonst setzte die Box den Platzhalter als neuen Schluessel/Kennwort
return {"ok": False, "error": (
f"{', '.join(hidden)}: das ist nur der Platzhalter fuer ein verborgenes Geheimnis, "
"nicht der echte Wert — so nicht senden. Geheimnisse aendert Stefan selbst "
"(FritzBox-Oberflaeche) oder er nennt den neuen Wert ausdruecklich.")}
logger.info("[fritzbox] %s %s %s args=%s", ip, svc["short"], action, list(args))
r = _tr064(ip, user, pw, svc["type"], svc["control"], action, args)
if not r.get("ok") and r.get("upnp_error") in _FB_2FA_CODES:
@@ -1419,7 +1426,15 @@ def _fb_call(ip: str, user: str, pw: str, params: dict) -> dict:
r = _tr064(ip, user, pw, svc["type"], svc["control"], action, args)
if not r.get("ok"):
return r
return {"ok": True, "result": {"ip": ip, "service": svc["short"], "action": action, **r["fields"]}}
# Geheimnisse, die die Box auf Lese-Anfragen herausgibt (WLAN-Schluessel,
# Kennwoerter, PINs), gehen NICHT an ARIA — ihre Antworten landen beim
# Sprachmodell. Stefan sieht sie in der FritzBox-Oberflaeche.
fields = {k: ("•••• (verborgen)" if _FB_SECRET_FIELD.search(k) and v else v) for k, v in r["fields"].items()}
return {"ok": True, "result": {"ip": ip, "service": svc["short"], "action": action, **fields}}
_FB_SECRET_FIELD = re.compile(r"Passphrase|Password|PreSharedKey|WEPKey|KeyPassphrase|Secret|PIN|Passwd|SharedKey",
re.IGNORECASE)
FB_BACKUP_DIR = os.environ.get("FB_BACKUP_DIR", "/data/fritzbox-backups")