diff --git a/app/routers/qualys.py b/app/routers/qualys.py
index 1388966..06a5ba9 100644
--- a/app/routers/qualys.py
+++ b/app/routers/qualys.py
@@ -8,7 +8,7 @@ from ..dependencies import get_db, get_current_user, get_user_perms, can_view, c
from ..services.qualys_service import (
sync_server_qualys, search_assets_api, get_all_tags_api,
create_tag_api, delete_tag_api, add_tag_to_asset_api,
- remove_tag_from_asset_api, resync_all_tags,
+ remove_tag_from_asset_api, resync_all_tags, get_vuln_counts,
)
from ..config import APP_NAME
@@ -408,13 +408,23 @@ async def qualys_search(request: Request, db=Depends(get_db),
api_msg = f"{len(assets)} résultat(s) — source: {source}"
+ # Enrichir avec vulnérabilités (severity 3,4,5, Confirmed/Potential, Active)
+ vuln_map = {}
+ if assets:
+ asset_ids = [str(a.qualys_asset_id) for a in assets if a.qualys_asset_id]
+ if asset_ids:
+ try:
+ vuln_map = get_vuln_counts(db, ",".join(asset_ids[:50]))
+ except Exception:
+ pass
+
all_tags = db.execute(text("SELECT qualys_tag_id, name FROM qualys_tags ORDER BY name")).fetchall()
ctx = base_context(request, db, user)
ctx.update({
"app_name": APP_NAME, "assets": assets, "search": search,
"field": field, "api_msg": api_msg,
- "all_tags": all_tags,
+ "all_tags": all_tags, "vuln_map": vuln_map,
"can_edit_qualys": can_edit(perms, "qualys"),
"msg": request.query_params.get("msg"),
})
diff --git a/app/services/qualys_service.py b/app/services/qualys_service.py
index f2bd53d..9213f76 100644
--- a/app/services/qualys_service.py
+++ b/app/services/qualys_service.py
@@ -369,3 +369,69 @@ def _find_asset_by_hostname(qualys_url, qualys_user, qualys_pass, hostname, prox
except Exception:
pass
return None
+
+
+def get_vuln_counts(db, qualys_asset_ids):
+ """Recupere le nombre de vulnerabilites actives severity 3,4,5 pour un ou plusieurs assets.
+ qualys_asset_ids: str (un ID ou liste separee par virgules)
+ Retourne dict {asset_id: {severity3, severity4, severity5, total, confirmed, potential}}
+ """
+ qualys_url, qualys_user, qualys_pass, qualys_proxy = _get_qualys_creds(db)
+ if not qualys_user or not qualys_asset_ids:
+ return {}
+ proxies = {"https": qualys_proxy, "http": qualys_proxy} if qualys_proxy else None
+
+ try:
+ r = requests.post(
+ f"{qualys_url}/api/2.0/fo/asset/host/vm/detection/",
+ data={
+ "action": "list",
+ "ids": str(qualys_asset_ids),
+ "severities": "3,4,5",
+ "status": "New,Active,Re-Opened",
+ "show_results": "0",
+ "output_format": "XML",
+ },
+ auth=(qualys_user, qualys_pass),
+ verify=False, timeout=120, proxies=proxies,
+ headers={"X-Requested-With": "Python"},
+ )
+ except Exception:
+ return {}
+
+ if r.status_code != 200:
+ return {}
+
+ txt = r.text
+ results = {}
+
+ for host_block in txt.split("