Skip to content

Commit 7852610

Browse files
committed
Allow vulnerability scans on arbitrary N|Solid refs
Known branches still use curated dependency lists, but unknown refs now fall back to probing every tracked dependency definition and keeping only the ones whose version parsers succeed against the checked-out tree. This lets the scanner run against release branches and ad hoc refs without having to pre-register each branch name in dependencies_per_branch. Also document the workflow input as an arbitrary N|Solid branch/ref and mark curated scans as incomplete when a curated dependency fails to resolve.
1 parent ba643e2 commit 7852610

2 files changed

Lines changed: 71 additions & 10 deletions

File tree

.github/workflows/check-vulns.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
nsolidStream:
77
type: string
88
default: 'main'
9+
description: 'N|Solid branch or ref to scan'
910
secrets:
1011
NVD_API_KEY:
1112
required: true
@@ -14,6 +15,7 @@ on:
1415
nsolidStream:
1516
type: string
1617
default: 'main'
18+
description: 'N|Solid branch or ref to scan'
1719

1820

1921
permissions:

dep_checker/main.py

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,64 @@ def default(self, obj):
103103
)
104104

105105

106+
def resolve_dependencies(
107+
repo_path: Path, repo_branch: str
108+
) -> tuple[dict[str, Dependency], list[str]]:
109+
"""Return the dependencies that can be parsed from the checked-out repo.
110+
111+
Known branches still use their curated dependency list. Unknown branches fall
112+
back to probing every tracked dependency definition and keeping only the ones
113+
whose version parser succeeds against the checkout.
114+
"""
115+
116+
configured_names = dependencies_per_branch.get(repo_branch)
117+
if configured_names is None:
118+
candidate_dependencies = dependencies_info
119+
print(
120+
f"Info: '{repo_branch}' is not explicitly configured; scanning all known dependency definitions"
121+
)
122+
else:
123+
candidate_dependencies = {
124+
name: dep
125+
for name, dep in dependencies_info.items()
126+
if name in configured_names
127+
}
128+
129+
available_dependencies: dict[str, Dependency] = {}
130+
skipped_dependencies: list[str] = []
131+
132+
for name, dep in candidate_dependencies.items():
133+
try:
134+
dep.version_parser(repo_path)
135+
except (
136+
FileNotFoundError,
137+
RuntimeError,
138+
ValueError,
139+
KeyError,
140+
IndexError,
141+
AttributeError,
142+
TypeError,
143+
OSError,
144+
) as exc:
145+
skipped_dependencies.append(f"{name}: {exc}")
146+
continue
147+
available_dependencies[name] = dep
148+
149+
if not available_dependencies:
150+
raise RuntimeError(
151+
f"No supported dependencies could be resolved from '{repo_branch}'"
152+
)
153+
154+
if skipped_dependencies:
155+
print(
156+
f"Info: Skipping {len(skipped_dependencies)} dependencies that are not present or not parseable in '{repo_branch}'"
157+
)
158+
for skipped in skipped_dependencies:
159+
print(f" - {skipped}")
160+
161+
return available_dependencies, skipped_dependencies
162+
163+
106164
def query_ghad(
107165
dependencies: dict[str, Dependency], gh_token: str, repo_path: Path
108166
) -> list[Vulnerability]:
@@ -237,7 +295,10 @@ def main() -> int:
237295
parser.add_argument(
238296
"node_repo_branch",
239297
metavar="NODE_REPO_BRANCH",
240-
help=f"the current branch of the Node repository (supports {supported_branches})",
298+
help=(
299+
"the current branch of the Node/N|Solid repository; known branches use "
300+
f"curated dependency lists, other branches are scanned by probing available dependencies ({supported_branches})"
301+
),
241302
)
242303
parser.add_argument(
243304
"--gh-token",
@@ -281,10 +342,6 @@ def main() -> int:
281342
raise RuntimeError(
282343
"Invalid argument: '{repo_path}' is not a valid Node git repository"
283344
)
284-
if repo_branch not in dependencies_per_branch:
285-
raise RuntimeError(
286-
f"Invalid argument: '{repo_branch}' is not a supported branch. Please use one of: {supported_branches}"
287-
)
288345
if gh_token is None:
289346
print(
290347
"Warning: GitHub authentication token not provided, skipping GitHub Advisory Database queries",
@@ -296,15 +353,17 @@ def main() -> int:
296353
file=sys.stderr,
297354
)
298355

299-
dependencies = {
300-
name: dep
301-
for name, dep in dependencies_info.items()
302-
if name in dependencies_per_branch[repo_branch]
303-
}
356+
dependencies, skipped_dependencies = resolve_dependencies(repo_path, repo_branch)
304357

305358
# Track whether every vulnerability source completed successfully. A partial scan must not
306359
# cause the reconciler to close issues for vulns that simply weren't queried this run.
307360
scan_complete = True
361+
if repo_branch in dependencies_per_branch and skipped_dependencies:
362+
scan_complete = False
363+
print(
364+
f"Warning: {len(skipped_dependencies)} curated dependencies could not be resolved for '{repo_branch}'",
365+
file=sys.stderr,
366+
)
308367

309368
ghad_vulnerabilities: list[Vulnerability] = []
310369
if gh_token is not None:

0 commit comments

Comments
 (0)