Skip to content

Commit 9bcd1d3

Browse files
committed
fixup
1 parent f9c5bf5 commit 9bcd1d3

2 files changed

Lines changed: 35 additions & 34 deletions

File tree

dep_checker/npm_audit.py

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -388,30 +388,31 @@ def merge_vulnerability(vuln) -> None:
388388
advisory_aliases=self.advisory_aliases(vuln["advisory"], preferred_id),
389389
)
390390
)
391+
try:
392+
global_advisories = self.fetch_global_advisories(packages_for_global_advisories)
393+
except Exception as exc:
394+
self.failed_packages.append(
395+
f"{package_dir}: global advisory query failed: {exc}"
396+
)
397+
logger.warning(f"Skipping global advisory query for {package_dir}: {exc}")
398+
global_advisories = []
399+
391400
for package in packages_for_global_advisories:
392-
try:
393-
for vuln in self.query_global_advisory_vulnerabilities(package):
394-
merge_vulnerability(
395-
vulnerability_class(
396-
id=vuln["id"],
397-
url=vuln["url"],
398-
dependency=package["name"],
399-
version=package["version"],
400-
source="npm",
401-
severity=vuln.get("severity"),
402-
via=[vuln["summary"]] if vuln.get("summary") else [],
403-
fix_available=vuln.get("fix_available"),
404-
main_dep_name=main_dep_name,
405-
main_dep_path=main_dep_path,
406-
advisory_aliases=vuln.get("aliases", []),
407-
)
401+
for vuln in self.match_global_advisories(package, global_advisories):
402+
merge_vulnerability(
403+
vulnerability_class(
404+
id=vuln["id"],
405+
url=vuln["url"],
406+
dependency=package["name"],
407+
version=package["version"],
408+
source="npm",
409+
severity=vuln.get("severity"),
410+
via=[vuln["summary"]] if vuln.get("summary") else [],
411+
fix_available=vuln.get("fix_available"),
412+
main_dep_name=main_dep_name,
413+
main_dep_path=main_dep_path,
414+
advisory_aliases=vuln.get("aliases", []),
408415
)
409-
except Exception as exc:
410-
self.failed_packages.append(
411-
f"{package_dir}: global advisory query failed for {package['name']}@{package['version']}: {exc}"
412-
)
413-
logger.warning(
414-
f"Skipping global advisory query for {package['name']}@{package['version']}: {exc}"
415416
)
416417

417418
for package in packages:
@@ -456,8 +457,7 @@ def merge_vulnerability(vuln) -> None:
456457
logger.info(f"Parsed {len(vulnerabilities)} merged advisory matches from {package_dir}")
457458
return vulnerabilities
458459

459-
def query_global_advisory_vulnerabilities(self, package: Dict[str, str]) -> List[Dict[str, object]]:
460-
advisories = self.fetch_global_advisories(package["name"], package["version"])
460+
def match_global_advisories(self, package: Dict[str, str], advisories: List[Dict]) -> List[Dict[str, object]]:
461461
results: List[Dict[str, object]] = []
462462
seen_ids: set[str] = set()
463463
for advisory in advisories:
@@ -488,16 +488,18 @@ def query_global_advisory_vulnerabilities(self, package: Dict[str, str]) -> List
488488
})
489489
return results
490490

491-
def fetch_global_advisories(self, package_name: str, version: str) -> List[Dict]:
491+
def fetch_global_advisories(self, packages: List[Dict[str, str]]) -> List[Dict]:
492+
if not packages:
493+
return []
492494
cache = getattr(self, "_global_advisory_cache", None)
493495
if cache is None:
494496
cache = self._global_advisory_cache = {}
495-
key = (package_name, version)
496-
if key in cache:
497-
return cache[key]
497+
requested = tuple(sorted({f"{package['name']}@{package['version']}" for package in packages}))
498+
if requested in cache:
499+
return cache[requested]
498500
query = urllib.parse.urlencode([
499501
("ecosystem", "npm"),
500-
("affects[]", f"{package_name}@{version}"),
502+
("affects", ",".join(requested)),
501503
("per_page", "100"),
502504
])
503505
url = f"https://api.github.com/advisories?{query}"
@@ -506,15 +508,14 @@ def fetch_global_advisories(self, package_name: str, version: str) -> List[Dict]
506508
"X-GitHub-Api-Version": GITHUB_API_VERSION,
507509
"User-Agent": "nsolid-dependency-vuln-assessments",
508510
}
509-
if self.gh_token is not None:
510-
headers["Authorization"] = f"Bearer {self.gh_token}"
511511
request = urllib.request.Request(url, headers=headers)
512512
with urllib.request.urlopen(request, timeout=min(self.timeout, 30)) as response:
513513
payload = json.load(response)
514514
if not isinstance(payload, list):
515+
logger.warning(f"Global advisory query returned non-list payload for {len(requested)} packages: {payload}")
515516
return []
516-
cache[key] = [item for item in payload if isinstance(item, dict)]
517-
return cache[key]
517+
cache[requested] = [item for item in payload if isinstance(item, dict)]
518+
return cache[requested]
518519

519520
def preferred_global_advisory_cve(self, advisory: Dict) -> Optional[str]:
520521
for identifier in advisory.get("identifiers") or []:

dep_checker/test_npm_audit.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ def read(self):
388388
npm_audit.urllib.request.urlopen = lambda *args, **kwargs: FakeResponse()
389389
try:
390390
checker = NPMAuditChecker(Path("/tmp"), timeout=60, gh_token="token")
391-
assert checker.fetch_global_advisories("example", "1.0.0") == []
391+
assert checker.fetch_global_advisories([{"name": "example", "version": "1.0.0"}]) == []
392392
finally:
393393
npm_audit.urllib.request.urlopen = original_urlopen
394394

0 commit comments

Comments
 (0)