From 946dff5d0896433b57eead9db4fdda2eff314cca Mon Sep 17 00:00:00 2001 From: Christian Manivong Date: Fri, 23 Oct 2026 08:42:31 +0200 Subject: [PATCH] fix: what bandit and the remaining lint rules found - The MD5 of the password is what the phone's login API expects, the wire format and no protection of ours (the session runs over HTTPS): hashlib.md5(..., usedforsecurity=False) (B324). The digest is the same. - A failed logout in close() and an unreadable system info in get_facts() now log at debug level (B110), so a swallowed failure leaves a trace; the module gets its logger. - The comment on the "yealink" fingerprint rule moves above it (ruff format had split the line around it) and is in English. --- napalm_yealink/yealink.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/napalm_yealink/yealink.py b/napalm_yealink/yealink.py index ba10874..6bc22e1 100644 --- a/napalm_yealink/yealink.py +++ b/napalm_yealink/yealink.py @@ -14,6 +14,7 @@ automatically) or via ``optional_args={"verify_ssl": False}``. from __future__ import annotations import hashlib +import logging import socket from typing import Any @@ -22,6 +23,8 @@ from napalm.base.exceptions import ConnectionException from napalm_device_types import FingerprintRule, PhoneDriver from requests.exceptions import RequestException +logger = logging.getLogger(__name__) + class YealinkDriver(PhoneDriver): """NAPALM driver for Yealink IP phones (T-series, W-series, CP-series, VP-series).""" @@ -35,9 +38,8 @@ class YealinkDriver(PhoneDriver): "80:5E:0C", # YEALINK(XIAMEN) NETWORK TECHNOLOGY — IEEE, verifiziert an T58V ] HTTP_FINGERPRINT = [ - FingerprintRule( - "yealink", weight=10.0 - ), # nicht mandatory: Yealink/api redirect hat kein "yealink" im Body + # Not mandatory: the redirect of some models to their API page has no "yealink" in it. + FingerprintRule("yealink", weight=10.0), FingerprintRule("sip-t", weight=5.0), FingerprintRule("sip-w", weight=5.0), FingerprintRule("sip-cp", weight=5.0), @@ -70,7 +72,9 @@ class YealinkDriver(PhoneDriver): def open(self) -> None: self._session = requests.Session() self._session.verify = self._verify_ssl - pw_hash = hashlib.md5(self.password.encode()).hexdigest() + # The login API takes the password as an MD5 hex digest: the wire format, not a + # protection (the session runs over HTTPS). + pw_hash = hashlib.md5(self.password.encode(), usedforsecurity=False).hexdigest() try: resp = self._session.post( f"{self._base_url}{self._LOGIN_PATH}", @@ -92,7 +96,7 @@ class YealinkDriver(PhoneDriver): timeout=5, ) except Exception: - pass + logger.debug("Logging out of the phone failed: ignored", exc_info=True) self._session.close() self._session = None @@ -123,7 +127,7 @@ class YealinkDriver(PhoneDriver): payload = data.get("data") or data.get("error") or {} info = payload if isinstance(payload, dict) else {} except Exception: - pass + logger.debug("Reading the system info failed: ignored", exc_info=True) model = info.get("phoneName") or info.get("model") or "Yealink" firmware = info.get("firmware") or info.get("firmwareVersion") or ""