diff --git a/app/services/qualys_service.py b/app/services/qualys_service.py
index c0f3a8b..94a7534 100644
--- a/app/services/qualys_service.py
+++ b/app/services/qualys_service.py
@@ -17,11 +17,12 @@ CACHE_TTL = 600 # 10 minutes
def _get_qualys_creds(db):
- """Recupere les credentials Qualys depuis les secrets chiffres"""
- url = get_secret(db, "qualys_url") or "https://qualysapi.qualys.eu"
- user = get_secret(db, "qualys_user") or ""
- pwd = get_secret(db, "qualys_pass") or ""
- proxy = get_secret(db, "qualys_proxy") or ""
+ """Recupere les credentials Qualys depuis les secrets chiffres.
+ .strip() defensif : un copier-coller peut ajouter newline/CR."""
+ url = (get_secret(db, "qualys_url") or "https://qualysapi.qualys.eu").strip()
+ user = (get_secret(db, "qualys_user") or "").strip()
+ pwd = (get_secret(db, "qualys_pass") or "").strip()
+ proxy = (get_secret(db, "qualys_proxy") or "").strip()
bypass = (get_secret(db, "qualys_bypass_proxy") or "").lower() == "true"
if bypass:
proxy = ""
@@ -87,15 +88,22 @@ def search_assets_api(db, query, field="name", operator="CONTAINS", force_refres
return {"ok": False, "msg": f"Erreur API: {e}", "assets": []}
if r.status_code != 200 or "SUCCESS" not in r.text:
- # Inclure le détail Qualys (errorMessage / errorResolution sont dans le XML)
+ # Extraire un max d'info Qualys pour debug
import re as _re
err_msg = ""
+ m = _re.search(r"([^<]+)", r.text or "")
+ if m: err_msg += " [" + m.group(1).strip() + "]"
m = _re.search(r"([^<]+)", r.text or "")
if m: err_msg += " | errorMessage: " + m.group(1).strip()
m = _re.search(r"([^<]+)", r.text or "")
if m: err_msg += " | errorResolution: " + m.group(1).strip()
- m = _re.search(r"([^<]+)", r.text or "")
- if m: err_msg = " [" + m.group(1).strip() + "]" + err_msg
+ # Si Qualys retourne message (legacy /api/2.0/fo)
+ m = _re.search(r']*status="FAILED"[^>]*>\s*([^<]+?)\s*',
+ r.text or "", _re.DOTALL)
+ if m: err_msg += " | RETURN: " + m.group(1).strip()
+ # Fallback : dump brut tronqué (utile si XML non standard)
+ if not err_msg and r.text:
+ err_msg = " | RAW: " + r.text[:500].replace("\n", " ")
return {"ok": False,
"msg": f"API HTTP {r.status_code}{err_msg}",
"assets": []}