fix: race conditions in lock pop, CSV formula injection, serialize_finding None leak, consolidate plans, update docs
This commit is contained in:
@@ -76,21 +76,24 @@ async def harvest(
|
||||
_url_locks.pop(download_url, None)
|
||||
return None
|
||||
|
||||
active_found = False
|
||||
async with lock:
|
||||
try:
|
||||
# Re-check DB in case another task already created and finished a scan
|
||||
active = await session.scalar(
|
||||
select(Scan.id).where(
|
||||
Scan.nexus_asset_url == download_url,
|
||||
Scan.status.in_([ScanStatus.PENDING.value, ScanStatus.SCANNING.value]),
|
||||
)
|
||||
# Re-check DB in case another task already created and finished a scan
|
||||
active = await session.scalar(
|
||||
select(Scan.id).where(
|
||||
Scan.nexus_asset_url == download_url,
|
||||
Scan.status.in_([ScanStatus.PENDING.value, ScanStatus.SCANNING.value]),
|
||||
)
|
||||
if active:
|
||||
log.info("Already scanning this URL, skipping")
|
||||
return None
|
||||
finally:
|
||||
async with _url_lock:
|
||||
_url_locks.pop(download_url, None)
|
||||
)
|
||||
if active:
|
||||
log.info("Already scanning this URL, skipping")
|
||||
active_found = True
|
||||
|
||||
async with _url_lock:
|
||||
_url_locks.pop(download_url, None)
|
||||
|
||||
if active_found:
|
||||
return None
|
||||
|
||||
scan = Scan(
|
||||
package_name=package_name,
|
||||
|
||||
@@ -21,6 +21,7 @@ from ..db.engine import get_session
|
||||
from ..db.models import Scan
|
||||
from ..db.queries import build_package_list_query
|
||||
from ..schemas import PackageDetailOut, PackageListResponse, serialize_finding
|
||||
from .api_scans import _csv_safe
|
||||
|
||||
router = APIRouter(prefix="/api/v1/packages", tags=["packages"])
|
||||
|
||||
@@ -102,8 +103,8 @@ async def export_packages_csv(
|
||||
for r in rows:
|
||||
writer.writerow(
|
||||
[
|
||||
r.pkg_name,
|
||||
r.pkg_ver,
|
||||
_csv_safe(r.pkg_name),
|
||||
_csv_safe(r.pkg_ver),
|
||||
r.ecosystem,
|
||||
r.repository,
|
||||
r.last_scan.isoformat() if r.last_scan else "",
|
||||
|
||||
@@ -21,6 +21,13 @@ from ..db.models import Scan
|
||||
from ..db.queries import build_scan_list_query, get_dashboard_stats
|
||||
from ..schemas import ScanDetailOut, ScanListResponse, StatsResponse, serialize_finding
|
||||
|
||||
|
||||
def _csv_safe(value: str) -> str:
|
||||
if value and value[0] in "=+-@":
|
||||
return "'" + value
|
||||
return value
|
||||
|
||||
|
||||
router = APIRouter(prefix="/api/v1/scans", tags=["scans"])
|
||||
|
||||
|
||||
@@ -112,8 +119,8 @@ async def export_scans_csv(
|
||||
writer.writerow(
|
||||
[
|
||||
s.id,
|
||||
s.package_name,
|
||||
s.package_version,
|
||||
_csv_safe(s.package_name),
|
||||
_csv_safe(s.package_version),
|
||||
s.ecosystem,
|
||||
s.repository,
|
||||
s.status,
|
||||
@@ -121,7 +128,7 @@ async def export_scans_csv(
|
||||
s.flagged,
|
||||
s.started_at.isoformat() if s.started_at else "",
|
||||
s.finished_at.isoformat() if s.finished_at else "",
|
||||
s.error_message or "",
|
||||
_csv_safe(s.error_message or ""),
|
||||
s.sha256 or "",
|
||||
]
|
||||
)
|
||||
|
||||
@@ -262,13 +262,12 @@ async def analyze_finding_htmx(
|
||||
return _render("_llm_spinner.html", request=request, finding_id=finding_id)
|
||||
|
||||
async with lock:
|
||||
try:
|
||||
finding.report = {"status": "analyzing"}
|
||||
await session.commit()
|
||||
report = await analyze_finding(finding.data)
|
||||
finally:
|
||||
async with _llm_lock:
|
||||
_llm_locks.pop(finding_id, None)
|
||||
finding.report = {"status": "analyzing"}
|
||||
await session.commit()
|
||||
report = await analyze_finding(finding.data)
|
||||
|
||||
async with _llm_lock:
|
||||
_llm_locks.pop(finding_id, None)
|
||||
|
||||
if report is None:
|
||||
finding.report = None
|
||||
|
||||
@@ -139,5 +139,5 @@ def serialize_finding(finding) -> dict:
|
||||
"created_at": finding.created_at.isoformat() if finding.created_at else None,
|
||||
}
|
||||
for field in _FINDING_DATA_FIELDS:
|
||||
result[field] = finding.data.get(field, "")
|
||||
result[field] = finding.data.get(field) or ""
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user