-
Notifications
You must be signed in to change notification settings - Fork 5
Harden cve-fix with pre-fix scanning, binary verification, PR dedup and input guardrails #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
amir-yogev-gh
merged 20 commits into
flightctl:main
from
amir-yogev-gh:cve-fix-hardening
May 12, 2026
Merged
Changes from 7 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
1e799a6
Harden cve-fix with pre-fix scanning, binary verification, PR dedup, …
amir-yogev-gh 3b24040
Fix lint failure: replace absolute path with ${TMPDIR} in validate.md
amir-yogev-gh c010090
Fix inconsistent error handling in check_existing_prs.py
amir-yogev-gh 3487ee9
Fix check_manifests returning first file line instead of matching line
amir-yogev-gh f1e571d
Fix scanner exit code misinterpretation in scan.py
amir-yogev-gh aa23c02
Fix scanner exit code misinterpretation in verify.py
amir-yogev-gh 1775d83
Add VEX justification to scan output for Jira ticket closure
amir-yogev-gh 1c891de
Fix in_base_image verdict misclassifying absent CVEs
amir-yogev-gh 198902a
Write error-state JSON on input validation failures
amir-yogev-gh 8d45564
Distinguish scanner crashes from meaningful results in present_by_ver…
amir-yogev-gh 44f341f
Add GOTOOLCHAIN download fallback to verify_go
amir-yogev-gh 5b23558
Move shutil import to module scope and wrap temp dir in try/finally
amir-yogev-gh 162503d
Extract shared code to _common.py and use subprocess cwd= instead of …
amir-yogev-gh 85f02c3
Restrict package diff match to added/removed lines only
amir-yogev-gh 6c1198b
Document npm lockfile side effect and search-script exit code convention
amir-yogev-gh aea3a88
Raise on gh query failures instead of returning None
amir-yogev-gh 70d3949
Reject build_location paths that escape repo_dir in scan.py
amir-yogev-gh 35caefe
Reject build_location paths that escape repo_dir in verify.py
amir-yogev-gh 64849a2
Keep scan_tool canonical in verify_node to fix exit code normalization
amir-yogev-gh 6bc0ea7
Normalize path styles in validate.md command examples
amir-yogev-gh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| --- | ||
| name: cve-fix:scan | ||
| description: "Scan the repository to confirm the CVE is present before patching" | ||
| --- | ||
| # /scan | ||
|
|
||
| Read `../skills/controller.md` and follow it. | ||
|
|
||
| Dispatch the **scan** phase. Context: | ||
|
|
||
| $ARGUMENTS |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| #!/usr/bin/env python3 | ||
| """Check for existing open PRs that address a CVE before creating duplicates. | ||
|
|
||
| Searches by CVE ID, package name, and diff content to catch PRs from | ||
| other CVEs that bump the same dependency, as well as Dependabot/Renovate PRs. | ||
|
|
||
| Usage: check_existing_prs.py <repo_full> <target_branch> <cve_id> <package> | ||
|
|
||
| Output: JSON to stdout with match details. | ||
| Exit codes: | ||
| 0 — matching PR found (caller should consider skipping) | ||
| 1 — no matching PR found (safe to proceed) | ||
| 2 — GitHub API query failed (treat as unknown) | ||
|
|
||
| Requires: gh CLI authenticated and on PATH. | ||
| """ | ||
|
|
||
| import json | ||
| import subprocess | ||
| import sys | ||
|
|
||
|
|
||
| def gh(*args: str) -> tuple[int, str]: | ||
| """Run a gh CLI command, return (exit_code, stdout).""" | ||
| result = subprocess.run( | ||
| ["gh", *args], | ||
| capture_output=True, text=True, timeout=60, | ||
| ) | ||
| return result.returncode, result.stdout.strip() | ||
|
|
||
|
|
||
| def search_by_cve(repo: str, branch: str, cve_id: str) -> dict | None: | ||
| """Search for an open PR whose title/body mentions this CVE ID.""" | ||
| code, out = gh( | ||
| "pr", "list", "--repo", repo, "--state", "open", | ||
| "--base", branch, "--search", cve_id, | ||
| "--json", "number,title,url", "--jq", ".[0]", | ||
| ) | ||
| if code != 0: | ||
| return None | ||
| if not out or out == "null": | ||
| return None | ||
| try: | ||
| return json.loads(out) | ||
| except json.JSONDecodeError: | ||
| return None | ||
|
|
||
|
|
||
| def search_by_bot(repo: str, branch: str, package: str) -> dict | None: | ||
| """Search for Dependabot/Renovate PRs that bump the same package.""" | ||
| code, out = gh( | ||
| "pr", "list", "--repo", repo, "--state", "open", | ||
| "--base", branch, "--search", package, | ||
| "--json", "number,title,url,author", | ||
| "--jq", | ||
| '[.[] | select(.author.login | test("dependabot|renovate|renovate-bot"; "i"))] | .[0]', | ||
| ) | ||
| if code != 0 or not out or out == "null": | ||
| return None | ||
| try: | ||
| return json.loads(out) | ||
| except json.JSONDecodeError: | ||
| return None | ||
|
|
||
|
|
||
| def search_by_package(repo: str, branch: str, package: str) -> dict | None: | ||
| """Search for security/fix PRs whose diff touches the same package.""" | ||
| code, out = gh( | ||
| "pr", "list", "--repo", repo, "--state", "open", | ||
| "--base", branch, "--search", package, | ||
| "--json", "number,title,url,headRefName", | ||
| "--jq", | ||
| '[.[] | select(.title | test("cve|security|fix|bump|update"; "i"))]', | ||
| ) | ||
| if code != 0 or not out or out in ("null", "[]"): | ||
| return None | ||
|
|
||
| try: | ||
| candidates = json.loads(out) | ||
| except json.JSONDecodeError: | ||
| return None | ||
|
|
||
| for pr in candidates: | ||
| pr_num = str(pr.get("number", "")) | ||
| if not pr_num: | ||
| continue | ||
| diff_code, diff_out = gh("pr", "diff", pr_num, "--repo", repo) | ||
| if diff_code == 0 and package in diff_out: | ||
|
amir-yogev-gh marked this conversation as resolved.
Outdated
|
||
| return pr | ||
|
|
||
| return None | ||
|
|
||
|
|
||
| def main() -> int: | ||
| if len(sys.argv) < 5 or sys.argv[1] == "--help": | ||
| print( | ||
| "Usage: check_existing_prs.py <repo_full> <target_branch> <cve_id> <package>\n" | ||
| "\n" | ||
| "Check for existing open PRs that address a CVE before creating duplicates.\n" | ||
| "\n" | ||
| "Arguments:\n" | ||
| " repo_full Full repository name (e.g., org/repo)\n" | ||
| " target_branch Target branch to check PRs against\n" | ||
| " cve_id CVE identifier (e.g., CVE-2024-12345)\n" | ||
| " package Package name to search for in PR titles and diffs", | ||
| file=sys.stderr, | ||
| ) | ||
| return 2 | ||
|
|
||
| repo, branch, cve_id, package = sys.argv[1:5] | ||
|
|
||
| searches: list[tuple[str, callable]] = [ | ||
| ("exact_cve", lambda: search_by_cve(repo, branch, cve_id)), | ||
| ("bot_update", lambda: search_by_bot(repo, branch, package)), | ||
| ("same_package", lambda: search_by_package(repo, branch, package)), | ||
| ] | ||
|
|
||
| for match_type, search_fn in searches: | ||
| try: | ||
| pr = search_fn() | ||
| except (subprocess.TimeoutExpired, OSError, Exception) as exc: | ||
|
amir-yogev-gh marked this conversation as resolved.
Outdated
|
||
| print(json.dumps({"found": False, "match_type": "none", "error": str(exc)})) | ||
| return 2 | ||
|
|
||
| if pr: | ||
| print(json.dumps({ | ||
| "found": True, | ||
| "match_type": match_type, | ||
| "number": pr.get("number"), | ||
| "title": pr.get("title"), | ||
| "url": pr.get("url"), | ||
| })) | ||
| return 0 | ||
|
|
||
| print(json.dumps({"found": False, "match_type": "none"})) | ||
| return 1 | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| raise SystemExit(main()) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.