-
Notifications
You must be signed in to change notification settings - Fork 29
fix: MCP-first Jira auth and diagnose Ambient env var accessibility #104
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
base: main
Are you sure you want to change the base?
Changes from all commits
d238e1a
16eaf6c
effc57b
9f94c2f
5e46a41
4cdb7b5
5d0e621
ca57c02
c5a3928
6158357
4d5269b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,12 @@ | |||||||||||||||||||||||||||||||||||||||||||||||
| ## Purpose | ||||||||||||||||||||||||||||||||||||||||||||||||
| Implement secure remediations for prioritized CVEs through dependency updates, patches, code changes, or compensating controls. This command executes the actual fixes that eliminate vulnerabilities. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ## Mandatory Execution Rule | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **EVERY step in the Process section below MUST be executed in order. NO step may be skipped, abbreviated, or assumed complete without actually running it.** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| If a step produces no output (e.g., no `.cve-fix/` folder found, no tests discovered), log that result explicitly and continue. Do not silently skip any step. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ## Execution Style | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **Be concise. Brief status + final summary only.** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -33,6 +39,11 @@ Summary: | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 1. **Load CVEs from Find Output or User-Specified Jira Issue** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **Supported flags:** | ||||||||||||||||||||||||||||||||||||||||||||||||
| - `--automerge` — After creating each PR, enable GitHub's automerge so the PR merges automatically once all required checks pass. Off by default — the user must explicitly opt in. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Parse this flag before processing Jira issues. Store as `AUTOMERGE=true/false`. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **Option A: User specifies one or more Jira issues** | ||||||||||||||||||||||||||||||||||||||||||||||||
| - If user provides one or more Jira issue IDs (e.g., `/cve.fix RHOAIENG-4973` or `/cve.fix RHOAIENG-4973 RHOAIENG-5821`): | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Process each issue independently -- extract CVE ID and component from each | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -202,15 +213,28 @@ Summary: | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| If `PUSH_ACCESS` is `false` or the push fails: | ||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Create a fork under the authenticated user's account | ||||||||||||||||||||||||||||||||||||||||||||||||
| gh repo fork "$REPO_FULL" --clone=false | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| FORK_USER=$(gh api user --jq '.login') | ||||||||||||||||||||||||||||||||||||||||||||||||
| FORK_REPO="${FORK_USER}/${REPO_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Add fork as a remote | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Create fork if it doesn't exist yet | ||||||||||||||||||||||||||||||||||||||||||||||||
| gh repo fork "$REPO_FULL" --clone=false 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Sync fork branches with upstream — REQUIRED to ensure fix branches | ||||||||||||||||||||||||||||||||||||||||||||||||
| # are based on current upstream code, not a stale fork. | ||||||||||||||||||||||||||||||||||||||||||||||||
| # This syncs all branches in the fork with the upstream repo. | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Syncing fork ${FORK_REPO} with upstream ${REPO_FULL}..." | ||||||||||||||||||||||||||||||||||||||||||||||||
| gh repo sync "${FORK_REPO}" --source "$REPO_FULL" --branch "$TARGET_BRANCH" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [ $? -ne 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "⚠️ Fork sync failed — fix branch may be based on stale code. Proceeding with caution." | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "✅ Fork branch ${TARGET_BRANCH} synced with upstream" | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Add fork as a remote and fetch the synced branch | ||||||||||||||||||||||||||||||||||||||||||||||||
| cd "$REPO_DIR" | ||||||||||||||||||||||||||||||||||||||||||||||||
| git remote add fork "https://github.com/${FORK_REPO}.git" | ||||||||||||||||||||||||||||||||||||||||||||||||
| git remote add fork "https://github.com/${FORK_REPO}.git" 2>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||||||
| git fetch fork "$TARGET_BRANCH" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Push fix branch to fork, PR targets the original repo | ||||||||||||||||||||||||||||||||||||||||||||||||
| git push fork "$FIX_BRANCH" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -258,11 +282,34 @@ Summary: | |||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 4.5. **Load Global Fix Guidance from `.cve-fix/` Folder** | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Runs ONCE after all repos are cloned, BEFORE any fixes. Builds a global knowledge base from `.cve-fix/` folders across all cloned repos. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Check every cloned repo for `.cve-fix/`, read ALL files (e.g., `examples.md`, `config.json`, `dependencies.md`, `pitfalls.md`), and merge into a single context. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Extract: dependency co-upgrades, lock file requirements, version upgrade patterns, branch-specific instructions, known working fix versions, testing requirements, common pitfalls. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Apply this guidance to ALL subsequent steps (5-11). Guidance from any repo applies globally; when conflicts exist, prefer the repo-specific instruction. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - If no `.cve-fix/` folders exist, proceed with default strategy. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **CRITICAL — MANDATORY. Do NOT skip. Must run before any fix is applied.** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Runs ONCE after all repos are cloned, BEFORE any fixes. Check every cloned repo for | ||||||||||||||||||||||||||||||||||||||||||||||||
| a `.cve-fix/` directory and read ALL files inside it. This guidance contains | ||||||||||||||||||||||||||||||||||||||||||||||||
| repo-specific fix patterns, known working versions, and pitfalls that directly affect | ||||||||||||||||||||||||||||||||||||||||||||||||
| whether the fix will succeed. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| for REPO_DIR in "${ALL_CLONED_REPOS[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| CVE_FIX_DIR="${REPO_DIR}/.cve-fix" | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -d "$CVE_FIX_DIR" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "📖 Reading fix guidance from ${REPO_DIR}/.cve-fix/" | ||||||||||||||||||||||||||||||||||||||||||||||||
| for FILE in "$CVE_FIX_DIR"/*; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo " Reading: $FILE" | ||||||||||||||||||||||||||||||||||||||||||||||||
| cat "$FILE" | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "ℹ️ No .cve-fix/ folder in ${REPO_DIR} — using default strategy" | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - Extract: dependency co-upgrades, lock file requirements, version upgrade patterns, | ||||||||||||||||||||||||||||||||||||||||||||||||
| branch-specific instructions, known working fix versions, testing requirements, pitfalls | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Apply this guidance to ALL subsequent steps (5-11) | ||||||||||||||||||||||||||||||||||||||||||||||||
| - When conflicts exist between repos, prefer the repo-specific instruction | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Always log the result** — either "guidance loaded from X" or "no .cve-fix/ found in any repo" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||
| > **Steps 5-11 repeat for EACH repository identified in Step 3.** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -565,19 +612,40 @@ This issue can be closed as 'Not a Bug / ${VEX_JUSTIFICATION}' if the above evid | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **How to check:** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Two searches are needed — bots like Dependabot and Renovate open PRs that fix the same | ||||||||||||||||||||||||||||||||||||||||||||||||
| vulnerability without mentioning the CVE ID, only the package name and version bump. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| REPO_FULL="opendatahub-io/models-as-a-service" # org/repo from mapping | ||||||||||||||||||||||||||||||||||||||||||||||||
| CVE_ID="CVE-YYYY-XXXXX" | ||||||||||||||||||||||||||||||||||||||||||||||||
| PACKAGE="urllib3" # extracted from Jira summary in Step 1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| TARGET_BRANCH="main" # from mapping or user input | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Search open PRs for this specific CVE ID targeting this branch | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXISTING_PR=$(gh pr list --repo "$REPO_FULL" --state open --base "$TARGET_BRANCH" --search "$CVE_ID" --json number,title,url,headRefName,baseRefName --jq '.[0]' 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXISTING_PR="" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Search 1: by CVE ID (catches our own PRs and manually created ones) | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXISTING_PR=$(gh pr list --repo "$REPO_FULL" --state open --base "$TARGET_BRANCH" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --search "$CVE_ID" --json number,title,url --jq '.[0]' 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Search 2: by package name (catches Dependabot/Renovate PRs that don't mention CVE ID) | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$EXISTING_PR" ] || [ "$EXISTING_PR" = "null" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXISTING_PR=$(gh pr list --repo "$REPO_FULL" --state open --base "$TARGET_BRANCH" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --search "$PACKAGE" --json number,title,url,author \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --jq '[.[] | select(.author.login | test("dependabot|renovate|renovate-bot"; "i"))] | .[0]' \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # If no bot PR, still check for any open PR bumping this package | ||||||||||||||||||||||||||||||||||||||||||||||||
| # (a human may have already opened a fix PR without mentioning the CVE) | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$EXISTING_PR" ] || [ "$EXISTING_PR" = "null" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| EXISTING_PR=$(gh pr list --repo "$REPO_FULL" --state open --base "$TARGET_BRANCH" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --search "$PACKAGE" --json number,title,url --jq '.[0]' 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+639
to
+642
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Package-name fallback can skip unrelated PRs on common package terms. At Line 597-Line 599, the third search picks the first open PR matching Proposed tightening-EXISTING_PR=$(gh pr list --repo "$REPO_FULL" --state open --base "$TARGET_BRANCH" \
- --search "$PACKAGE" --json number,title,url --jq '.[0]' 2>/dev/null)
+EXISTING_PR=$(gh pr list --repo "$REPO_FULL" --state open --base "$TARGET_BRANCH" \
+ --search "$PACKAGE" --json number,title,url \
+ --jq '[.[] | select(.title | test("(^|[^A-Za-z0-9])" + $pkg + "([^A-Za-z0-9]|$)"; "i"))
+ | select(.title | test("bump|upgrade|security|cve"; "i"))] | .[0]' \
+ --arg pkg "$PACKAGE" 2>/dev/null)Also applies to: 642-647 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| PR_NUMBER=$(echo "$EXISTING_PR" | jq -r '.number') | ||||||||||||||||||||||||||||||||||||||||||||||||
| PR_TITLE=$(echo "$EXISTING_PR" | jq -r '.title') | ||||||||||||||||||||||||||||||||||||||||||||||||
| PR_URL=$(echo "$EXISTING_PR" | jq -r '.url') | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "⏭️ Skipping $CVE_ID — existing open PR found:" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "⏭️ Skipping $CVE_ID — existing open PR found (may be Dependabot/Renovate):" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo " PR #${PR_NUMBER}: ${PR_TITLE}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo " URL: ${PR_URL}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -613,11 +681,13 @@ This issue can be closed as 'Not a Bug / ${VEX_JUSTIFICATION}' if the above evid | |||||||||||||||||||||||||||||||||||||||||||||||
| - Proceed with the fix (Step 6 onwards) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **Search strategy:** | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Search by exact CVE ID first (e.g., `CVE-2025-61726`) — this is the most reliable match | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Search 1 — by CVE ID**: catches our own PRs and any manually created ones | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Search 2 — by package name filtered to bots**: catches Dependabot/Renovate PRs that bump the vulnerable package without mentioning the CVE ID (e.g. "Bump urllib3 from 1.26.5 to 2.2.3") | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Search 3 — by package name broadly**: catches any human-opened PR for the same package, regardless of author | ||||||||||||||||||||||||||||||||||||||||||||||||
| - The `gh pr list --search` command searches PR titles and bodies | ||||||||||||||||||||||||||||||||||||||||||||||||
| - A single PR may address multiple CVEs (e.g., "fix: cve-2025-61726 and cve-2025-68121") — if ANY of the target CVEs appear in an existing PR, consider all CVEs in that PR as already handled | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **IMPORTANT: Only skip for OPEN PRs.** Closed or merged PRs should be ignored — if a previous PR was closed without merging (e.g., it was incorrect or superseded), it is valid to create a new fix PR for the same CVE. The `--state open` flag in the `gh pr list` command ensures only open PRs are checked. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Stale remote branches**: A previous automation run may have left a remote branch with the same name (e.g., `fix/cve-YYYY-XXXXX-attempt-1`) from a closed PR. If push fails due to a conflicting remote branch, increment the attempt number (e.g., `attempt-2`) or delete the stale remote branch with `git push origin --delete <branch-name>` before pushing. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - A single PR may address multiple CVEs — if any of the target CVEs or the affected package appears in an existing open PR, skip creating a duplicate | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **IMPORTANT: Only skip for OPEN PRs.** Closed or merged PRs should be ignored — it is valid to create a new fix PR for the same CVE if a previous PR was closed without merging. The `--state open` flag ensures only open PRs are checked. | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Stale remote branches**: If push fails due to a conflicting remote branch from a previous run, increment the attempt number (e.g., `attempt-2`) or delete the stale branch with `git push origin --delete <branch-name>`. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **Example output when PR exists:** | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -982,10 +1052,92 @@ This issue can be closed as 'Not a Bug / ${VEX_JUSTIFICATION}' if the above evid | |||||||||||||||||||||||||||||||||||||||||||||||
| **Full test log**: `artifacts/cve-fixer/fixes/test-results/test-run-20260218-143022.log` | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 10.5. **Post-Fix CVE Verification** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **CRITICAL — This step is MANDATORY. Do NOT skip it. Do NOT proceed to PR creation without completing this step.** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Source-level scanning (Step 5) checks the dependency manifests before the fix. | ||||||||||||||||||||||||||||||||||||||||||||||||
| This step verifies the fix actually worked by scanning the **compiled output** after | ||||||||||||||||||||||||||||||||||||||||||||||||
| the fix is applied. A source scan can give false negatives (e.g., go.mod updated but | ||||||||||||||||||||||||||||||||||||||||||||||||
| toolchain not recompiled, or a transitive dep overrides the fixed version at build time). | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **For Go projects (preferred — binary scan):** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Building and scanning binary to verify fix for CVE-${CVE_ID}..." | ||||||||||||||||||||||||||||||||||||||||||||||||
| cd "$REPO_DIR" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the binary with the fixed go.mod | ||||||||||||||||||||||||||||||||||||||||||||||||
| go build -o /tmp/fixed-binary-${REPO_NAME} ./... 2>&1 | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [ $? -eq 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Scan the compiled binary — this is the gold standard | ||||||||||||||||||||||||||||||||||||||||||||||||
| POST_SCAN_OUTPUT=$(GOTOOLCHAIN="go${TARGET_GO_VERSION}" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| govulncheck -mode binary /tmp/fixed-binary-${REPO_NAME} 2>&1) | ||||||||||||||||||||||||||||||||||||||||||||||||
| rm -f /tmp/fixed-binary-${REPO_NAME} | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "⚠️ Binary build failed — falling back to source scan" | ||||||||||||||||||||||||||||||||||||||||||||||||
| POST_SCAN_OUTPUT=$(GOTOOLCHAIN="go${TARGET_GO_VERSION}" govulncheck -show verbose ./... 2>&1) | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **For Python projects:** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Re-run pip-audit on the modified requirements file | ||||||||||||||||||||||||||||||||||||||||||||||||
| POST_SCAN_OUTPUT=$(pip-audit -r requirements.txt 2>&1) | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **For Node.js projects:** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Re-run npm audit after package.json changes | ||||||||||||||||||||||||||||||||||||||||||||||||
| npm install --package-lock-only 2>/dev/null # regenerate lockfile | ||||||||||||||||||||||||||||||||||||||||||||||||
| POST_SCAN_OUTPUT=$(npm audit --json 2>&1) | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **Check result:** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| if echo "$POST_SCAN_OUTPUT" | grep -q "$CVE_ID"; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| CVE_STILL_PRESENT=true | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| CVE_STILL_PRESENT=false | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1093
to
+1107
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Post-fix verification can produce false passes when scan command fails. At Line 1023, the command is executed without checking exit status, and the decision at Line 1027 only greps output for Proposed fix-POST_SCAN_OUTPUT=$(GOTOOLCHAIN="go${TARGET_GO_VERSION}" govulncheck -show verbose ./... 2>&1)
-# For Python: pip-audit -r requirements.txt 2>/dev/null
-# For Node: npm audit --json 2>/dev/null
-
-if echo "$POST_SCAN_OUTPUT" | grep -q "$CVE_ID"; then
+POST_SCAN_OUTPUT=""
+POST_SCAN_EXIT=0
+
+if [ -f "go.mod" ]; then
+ POST_SCAN_OUTPUT=$(GOTOOLCHAIN="go${TARGET_GO_VERSION}" govulncheck -show verbose ./... 2>&1)
+ POST_SCAN_EXIT=$?
+elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
+ POST_SCAN_OUTPUT=$(pip-audit -r requirements.txt 2>&1)
+ POST_SCAN_EXIT=$?
+elif [ -f "package.json" ]; then
+ POST_SCAN_OUTPUT=$(npm audit --json 2>&1)
+ POST_SCAN_EXIT=$?
+else
+ echo "⚠️ Could not determine scanner for repository; skipping PR creation for safety."
+ CVE_STILL_PRESENT=true
+fi
+
+if [ "${POST_SCAN_EXIT}" -ne 0 ]; then
+ echo "⚠️ Post-fix scan failed (exit ${POST_SCAN_EXIT}); skipping PR creation for safety."
+ CVE_STILL_PRESENT=true
+elif echo "$POST_SCAN_OUTPUT" | grep -q "$CVE_ID"; then
CVE_STILL_PRESENT=true
else
CVE_STILL_PRESENT=false
fiAlso applies to: 1036-1037 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **If CVE is gone** (`CVE_STILL_PRESENT=false`) → proceed to PR creation ✅ | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| **If CVE is still present** (`CVE_STILL_PRESENT=true`) → **do NOT create a PR**: | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Print: "❌ CVE-YYYY-XXXXX still detected after fix attempt in [repo] ([branch]). Fix was insufficient." | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Add a Jira comment: | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||
| COMMENT_TEXT="Automated fix attempted but CVE still detected after applying changes. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Fix attempted: ${FIX_DESCRIPTION} | ||||||||||||||||||||||||||||||||||||||||||||||||
| Post-fix scan: CVE still present in ${REPO_FULL} on branch ${TARGET_BRANCH} | ||||||||||||||||||||||||||||||||||||||||||||||||
| Scan date: $(date -u +%Y-%m-%dT%H:%M:%SZ) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Manual investigation required — the automated fix did not resolve this CVE. | ||||||||||||||||||||||||||||||||||||||||||||||||
| Possible causes: transitive dependency conflict, incorrect package targeted, or | ||||||||||||||||||||||||||||||||||||||||||||||||
| the fix requires additional changes beyond a version bump." | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| COMMENT_JSON=$(jq -n --arg body "$COMMENT_TEXT" '{"body": $body}') | ||||||||||||||||||||||||||||||||||||||||||||||||
| AUTH=$(echo -n "${JIRA_EMAIL}:${JIRA_API_TOKEN}" | base64) | ||||||||||||||||||||||||||||||||||||||||||||||||
| curl -s -X POST \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| -H "Authorization: Basic ${AUTH}" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| -H "Content-Type: application/json" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| -d "$COMMENT_JSON" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| "${JIRA_BASE_URL}/rest/api/3/issue/${JIRA_KEY}/comment" | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - Document in `artifacts/cve-fixer/fixes/fix-failed-CVE-YYYY-XXXXX.md` | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Skip to next CVE/branch — do not create PR for this one | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 11. **Create Pull Requests** | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **CRITICAL**: You MUST actually CREATE the PRs using `gh pr create` command | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **CRITICAL**: Create a SEPARATE PR for EACH CVE (NOT combined) | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **CRITICAL**: Only create PRs for CVEs that were ACTUALLY FIXED (not for CVEs that were already fixed in Step 5) | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **CRITICAL**: Only create PRs for CVEs that passed post-fix verification in Step 10.5 (not for CVEs that were already fixed in Step 5 or where the fix was insufficient) | ||||||||||||||||||||||||||||||||||||||||||||||||
| - For each CVE fix that was successfully committed and pushed: | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Generate PR title: `Security: Fix CVE-YYYY-XXXXX (<package-name>)` | ||||||||||||||||||||||||||||||||||||||||||||||||
| - **Extract Jira issue IDs for this CVE:** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1074,10 +1226,16 @@ This PR fixes **CVE-YYYY-XXXXX** by upgrading <package> from X.X.X to Y.Y.Y. | |||||||||||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| gh pr create \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| PR_URL=$(gh pr create \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --base <target-branch> \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --title "Security: Fix CVE-YYYY-XXXXX (<package-name>)" \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| --body "$PR_BODY" | ||||||||||||||||||||||||||||||||||||||||||||||||
| --body "$PR_BODY") | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Enable automerge if --automerge flag was passed | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$AUTOMERGE" = "true" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| gh pr merge --auto --squash "$PR_URL" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "✅ Automerge enabled on $PR_URL — will merge when checks pass" | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1229
to
+1238
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a guard before enabling automerge to avoid acting on an empty PR URL. At Line 1082 and Line 1088, automerge is attempted based only on Suggested fix- PR_URL=$(gh pr create \
+ PR_URL=$(gh pr create \
--base <target-branch> \
--title "Security: Fix CVE-YYYY-XXXXX (<package-name>)" \
--body "$PR_BODY")
# Enable automerge if --automerge flag was passed
- if [ "$AUTOMERGE" = "true" ]; then
+ if [ -z "$PR_URL" ]; then
+ echo "❌ PR creation did not return a URL; skipping automerge"
+ elif [ "$AUTOMERGE" = "true" ]; then
gh pr merge --auto --squash "$PR_URL"
echo "✅ Automerge enabled on $PR_URL — will merge when checks pass"
fi📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.0)[warning] 1082-1082: Code block style (MD046, code-block-style) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Capture the PR URL from the command output | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Save PR URL to fix implementation report | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1155,6 +1313,9 @@ EOF | |||||||||||||||||||||||||||||||||||||||||||||||
| - PR URL for the created pull request | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - **Already Fixed Report**: `artifacts/cve-fixer/fixes/already-fixed-CVE-YYYY-XXXXX.md` (if CVE confirmed not present via both scan and package check) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - **Fix Failed Report**: `artifacts/cve-fixer/fixes/fix-failed-CVE-YYYY-XXXXX.md` (if post-fix re-scan still detects the CVE) | ||||||||||||||||||||||||||||||||||||||||||||||||
| - Fix attempted, post-fix scan output, Jira comment added, manual review required | ||||||||||||||||||||||||||||||||||||||||||||||||
| - CVE ID, repository, and scan evidence | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| - **VEX Justified Report**: `artifacts/cve-fixer/fixes/vex-justified-CVE-YYYY-XXXXX.md` (if auto-detected VEX justification added to Jira) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1222,6 +1383,12 @@ Fix multiple specific Jira issues: | |||||||||||||||||||||||||||||||||||||||||||||||
| /cve.fix RHOAIENG-4973 RHOAIENG-5821 | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Fix and enable automerge on all created PRs (merges automatically when checks pass): | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
| /cve.fix --automerge | ||||||||||||||||||||||||||||||||||||||||||||||||
| /cve.fix RHOAIENG-4973 --automerge | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Fix with custom message: | ||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||
| /cve.fix Fix open CVEs found in latest scan | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
Repository: ambient-code/workflows
Length of output: 257
🏁 Script executed:
Repository: ambient-code/workflows
Length of output: 118
🏁 Script executed:
Repository: ambient-code/workflows
Length of output: 4118
🏁 Script executed:
Repository: ambient-code/workflows
Length of output: 200
🏁 Script executed:
Repository: ambient-code/workflows
Length of output: 5814
Search 3's broad package matching is by design, but consider documenting its false-positive trade-off.
The three-stage search strategy at lines 638-641 is intentional: Search 3 uses
--search "$PACKAGE"without additional filtering to catch human-opened PRs that may already address the CVE without mentioning it explicitly (e.g., "Bump urllib3 from 1.26.5 to 2.2.3"). This is documented in the comments at lines 684-686.However, the trade-off is real: for package names that are common words ("client", "utils", "config"), the
gh pr list --searchcommand can match unrelated PRs whose titles or bodies happen to contain these words. The jq filter.[0]then selects the first match, which may not actually be about updating the package.Rather than tightening the search with word boundaries or keyword filters (which would change the design intent), consider:
🤖 Prompt for AI Agents