fix: try/except in _scan_component, serialize_finding to prevent data injection, DRY LLM template, SUPPORTED_ECOSYSTEMS constant

This commit is contained in:
Marker689
2026-05-11 19:45:49 +03:00
parent 6743321463
commit a6cd20e41c
8 changed files with 67 additions and 83 deletions

View File

@@ -13,7 +13,7 @@ from ..constants import (
)
from ..db.engine import get_session
from ..db.models import Finding
from ..schemas import FindingsListResponse
from ..schemas import FindingsListResponse, serialize_finding
router = APIRouter(prefix="/api/v1/findings", tags=["findings"])
@@ -42,14 +42,5 @@ async def list_findings(
"total": total,
"limit": limit,
"offset": offset,
"findings": [
{
"id": f.id,
"scan_id": f.scan_id,
**f.data,
"report": f.report,
"created_at": f.created_at.isoformat() if f.created_at else None,
}
for f in findings
],
"findings": [serialize_finding(f) for f in findings],
}

View File

@@ -20,7 +20,7 @@ from ..core.nexus import parse_package_path
from ..db.engine import get_session
from ..db.models import Scan
from ..db.queries import build_package_list_query
from ..schemas import PackageDetailOut, PackageListResponse
from ..schemas import PackageDetailOut, PackageListResponse, serialize_finding
router = APIRouter(prefix="/api/v1/packages", tags=["packages"])
@@ -145,7 +145,7 @@ async def get_package(
all_findings: list[dict] = []
for s in scans:
for f in s.findings:
all_findings.append({"id": f.id, **f.data, "report": f.report})
all_findings.append(serialize_finding(f))
return {
"name": scans[0].package_name,

View File

@@ -19,7 +19,7 @@ from ..constants import (
from ..db.engine import get_session
from ..db.models import Scan
from ..db.queries import build_scan_list_query, get_dashboard_stats
from ..schemas import ScanDetailOut, ScanListResponse, StatsResponse
from ..schemas import ScanDetailOut, ScanListResponse, StatsResponse, serialize_finding
router = APIRouter(prefix="/api/v1/scans", tags=["scans"])
@@ -171,5 +171,5 @@ async def get_scan(scan_id: int, session: AsyncSession = Depends(get_session)) -
"error_message": scan.error_message,
"initiator": scan.initiator,
"source_ip": scan.source_ip,
"findings": [{"id": f.id, **f.data, "report": f.report} for f in scan.findings],
"findings": [serialize_finding(f) for f in scan.findings],
}

View File

@@ -159,40 +159,45 @@ async def nexus_webhook(
async def _scan_component(repository: str, name: str, version: str, ecosystem: str):
from ..core.nexus import nexus_get
params = urlencode(
{
"repository": repository,
"name": name,
"version": version,
"format": ecosystem,
}
)
api_path = f"/service/rest/v1/search?{params}"
try:
resp = await nexus_get(api_path)
resp.raise_for_status()
data = resp.json()
from ..core.nexus import nexus_get
params = urlencode(
{
"repository": repository,
"name": name,
"version": version,
"format": ecosystem,
}
)
api_path = f"/service/rest/v1/search?{params}"
try:
resp = await nexus_get(api_path)
resp.raise_for_status()
data = resp.json()
except Exception as e:
log.warning("Component lookup error for %s==%s: %s", name, version, e)
return
items = data.get("items", [])
if not items:
log.warning("No items found in search for %s==%s", name, version)
return
for item in items:
for asset in item.get("assets", []):
asset_path = _extract_asset_path(asset)
if not asset_path or not _is_package_asset(asset_path):
continue
download_url = asset.get("downloadUrl") or _build_download_url(
repository, asset_path
)
log.info("Scanning component asset: %s", asset_path)
async for session in get_session():
await harvest(download_url, repository, ecosystem, asset_path, session)
break
except Exception as e:
log.warning("Component lookup error for %s==%s: %s", name, version, e)
return
items = data.get("items", [])
if not items:
log.warning("No items found in search for %s==%s", name, version)
return
for item in items:
for asset in item.get("assets", []):
asset_path = _extract_asset_path(asset)
if not asset_path or not _is_package_asset(asset_path):
continue
download_url = asset.get("downloadUrl") or _build_download_url(repository, asset_path)
log.info("Scanning component asset: %s", asset_path)
async for session in get_session():
await harvest(download_url, repository, ecosystem, asset_path, session)
break
log.error("Component scan failed for %s==%s: %s", name, version, e)
async def _scan_in_background(