Skip to content

Commit 4c50369

Browse files
vmrh21claude
andcommitted
feat: scope CVE fixes to container chain and improve verification
- Parse container name and package from Jira ticket summary in Step 1 - Use container_to_repo_mapping in Step 3 to scope PRs to only the repos that build the affected container, not all component repos. Fallback to all repos when container cannot be parsed. - Add package version check (Step 5.2.1) alongside existing scanner: when scan doesn't find CVE, check dependency manifests directly (requirements.txt, go.mod, package.json) before skipping. Only skip when both scan AND version check find no evidence of the vulnerability. If package not found in manifests, still create PR with manual review note. - Add AI Evaluations full repo chain (ragas, garak, lm-evaluation-harness, trustyai-service-operator, eval-hub) with container mappings Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 332616b commit 4c50369

1 file changed

Lines changed: 95 additions & 29 deletions

File tree

workflows/cve-fixer/.claude/commands/cve.fix.md

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Summary:
4040
- Fetch the issue details from Jira API
4141
- Extract CVE ID from the issue summary
4242
- Extract component name from the issue
43+
- Extract container name from the issue summary (see below)
4344
- Proceed with this single CVE
4445
- Skip the `/cve.find` output lookup
4546

@@ -49,10 +50,34 @@ Summary:
4950
- Extract CVE IDs with their status from the markdown file
5051
- Filter for CVEs where `Status: Open` (unfixed vulnerabilities)
5152
- Extract component name from the find output (e.g., "AI Core Dashboard")
53+
- Extract container name from each issue summary (see below)
5254
- Collect ALL open CVEs (no filtering)
5355
- Proceed with all open CVEs found
5456

55-
**Result**: A list of CVEs to fix with their associated Jira issues and components
57+
**Extracting container and package from Jira summary (both options)**
58+
59+
Jira summaries follow the pattern:
60+
```
61+
CVE-YYYY-XXXXX <container-name>: <package>: <description>
62+
```
63+
Example:
64+
```
65+
CVE-2025-66418 rhoai/odh-llm-d-routing-sidecar-rhel9: urllib3: Unbounded decompression
66+
```
67+
68+
Parse each summary to extract:
69+
- **Container name**: the `rhoai/odh-*-rhel9` token (or similar) between the CVE ID and the first colon
70+
- **Package name**: the token after the first colon (e.g., `urllib3`, `grpc-go`, `aiohttp`)
71+
72+
```bash
73+
SUMMARY="CVE-2025-66418 rhoai/odh-llm-d-routing-sidecar-rhel9: urllib3: Unbounded decompression"
74+
CONTAINER=$(echo "$SUMMARY" | grep -oP '(?<=CVE-[0-9]+-[0-9]+ )[\w/.-]+(?=:)')
75+
PACKAGE=$(echo "$SUMMARY" | grep -oP '(?<=: )[\w._-]+(?=:)')
76+
```
77+
78+
Store `CONTAINER` and `PACKAGE` per CVE for use in Steps 3 and 5.
79+
80+
**Result**: A list of CVEs to fix with their associated Jira issues, components, containers, and package names
5681

5782
2. **Load Component-Repository Mapping**
5883
- Use `component-repository-mappings.json` from workspace root
@@ -92,23 +117,39 @@ Summary:
92117
- Proceed with mapped repository as documented below
93118

94119
3. **Identify Target Repositories**
95-
- Get list of ALL repositories from the mapping for the component
96-
- **IMPORTANT**: A single component may map to MULTIPLE repositories (e.g., an upstream repo and one or more downstream repos)
97-
- Each repository entry may have a `repo_type` field indicating `"upstream"` or `"downstream"`
98-
- For each repository, gather:
99-
- Repository name (e.g., "opendatahub-io/odh-dashboard")
100-
- Default branch (e.g., "main")
101-
- Active release branches (e.g., ["v2.29.0-fixes", "v2.28.0-fixes", "rhoai-3.0"])
102-
- Primary target branch for CVE fixes (from `cve_fix_workflow.primary_target`)
103-
- Backport targets from cve_fix_workflow
104-
- Repository type (monorepo vs single package)
105-
- Repo type: upstream or downstream (from `repo_type` field, defaults to upstream if absent)
106-
- Create initial list of ALL candidate repositories for the fix
107-
- **Multi-repo strategy**: When a component has both upstream and downstream repos:
108-
- Fix upstream first, then apply the same fix to downstream repos
109-
- Each repo gets its own clone, branch, PR, and verification cycle
110-
- The fix in downstream repos may be a cherry-pick or re-application of the upstream fix
111-
- Steps 4 through 11 are repeated for EACH repository in the list
120+
121+
**3.1: Use container to scope repos (preferred)**
122+
123+
If a `CONTAINER` was extracted in Step 1:
124+
- Look up `CONTAINER` in `container_to_repo_mapping` for the component
125+
- This gives the **primary repo** (e.g., `opendatahub-io/llm-d-routing-sidecar`)
126+
- From the `repositories` section, collect all repos that share the same logical chain as the primary repo:
127+
- The primary repo itself
128+
- Any repo with the same name but different org (upstream/midstream/downstream)
129+
- **This ensures only the repos relevant to that specific container get PRs** — not every repo under the component
130+
131+
Example: `rhoai/odh-llm-d-routing-sidecar-rhel9` maps to `red-hat-data-services/llm-d-routing-sidecar`.
132+
Only process repos in the routing-sidecar chain — not inference-scheduler or batch-gateway repos.
133+
134+
**3.2: Fallback — use all repos**
135+
136+
If no `CONTAINER` was extracted (summary doesn't match expected pattern):
137+
- Fall back to processing ALL repositories listed under the component
138+
- Log a warning: "⚠️ Could not extract container from summary — processing all component repos"
139+
140+
**3.3: For each target repo, gather:**
141+
- Repository name (e.g., "opendatahub-io/odh-dashboard")
142+
- Default branch (e.g., "main")
143+
- Active release branches (e.g., ["v2.29.0-fixes", "v2.28.0-fixes", "rhoai-3.0"])
144+
- Primary target branch for CVE fixes (from `cve_fix_workflow.primary_target`)
145+
- Backport targets from `cve_fix_workflow`
146+
- Repository type (monorepo vs single package)
147+
- Repo type: upstream or downstream (from `repo_type` field, defaults to upstream if absent)
148+
149+
**Multi-repo strategy**: When a container chain has upstream, midstream, and downstream repos:
150+
- Fix upstream first, then apply the same fix to midstream and downstream
151+
- Each repo gets its own clone, branch, PR, and verification cycle
152+
- Steps 4 through 11 are repeated for EACH repository in the list
112153

113154
4. **Clone or Use Existing Repository**
114155
- Always use `/tmp` for repository operations with unique dirs per repo
@@ -234,18 +275,43 @@ Summary:
234275
**5.2: Analyze Scan Results**
235276
236277
- Check if the target CVE appears in the scan results
237-
- **If CVE has already been fixed (not present in scan results)**:
238-
- **DO NOT create a PR** — the vulnerability is already resolved
278+
- **If CVE found in scan** → proceed with fix (confirmed vulnerable)
279+
- **If CVE NOT found in scan**do NOT skip immediately. Instead run Step 5.2.1 below.
280+
281+
**5.2.1: Package version check (when scan does not find CVE)**
282+
283+
Container-level CVEs may not be detected by source-level scanners because the vulnerable
284+
package may be installed via RPM, a transitive dependency, or a base image layer rather
285+
than declared directly in the manifest. If the scan returns no result, check the package
286+
version directly:
287+
288+
```bash
289+
# Use PACKAGE extracted from Jira summary in Step 1 (e.g., "urllib3", "grpc-go")
290+
291+
# Python — check requirements files
292+
grep -ri "${PACKAGE}" requirements*.txt setup.py pyproject.toml 2>/dev/null
293+
294+
# Go — check go.mod
295+
grep -i "${PACKAGE}" go.mod 2>/dev/null
296+
297+
# Node — check package.json
298+
grep -i "${PACKAGE}" package.json 2>/dev/null
299+
```
300+
301+
**Interpret results:**
302+
- **Package found at a version** → compare against CVE affected version range
303+
- If version is in affected range → proceed with fix
304+
- If version is already patched → mark as already fixed (see below)
305+
- **Package not found in any manifest** → it may be transitive or RPM-installed
306+
- **Still proceed with fix attempt** — try to add/pin the package at a safe version
307+
- Include note in PR: "⚠️ Package not found directly in manifests — may be a transitive or RPM-installed dependency. Manual review required to confirm fix is effective."
308+
- **Both scan AND version check find nothing** → mark as already fixed:
309+
- **DO NOT create a PR**
239310
- **Print to stdout**: "✅ CVE-YYYY-XXXXX is already fixed in [repository] ([branch]). No action needed."
240-
- **Document in artifacts**: Create a brief note in `artifacts/cve-fixer/fixes/already-fixed-CVE-YYYY-XXXXX.md` with:
241-
- CVE ID
242-
- Repository and branch checked
243-
- Scan results showing CVE is not present
244-
- Timestamp of verification
245-
- Note that Jira ticket may need manual closure
246-
- **Move to next CVE**: Skip all remaining steps for this CVE and proceed to the next one
247-
- **Note**: The Jira ticket may still be open — this is an issue management task, not a code fix task
248-
- Only proceed with remaining steps for CVEs that are confirmed as current vulnerabilities in the scan
311+
- **Document in artifacts**: `artifacts/cve-fixer/fixes/already-fixed-CVE-YYYY-XXXXX.md`
312+
- **Note**: Jira ticket may need manual closure
313+
314+
- Only skip the CVE entirely when BOTH the scan AND the direct package check find no evidence of the vulnerability
249315
250316
**5.3: Check for Existing Open PRs**
251317

0 commit comments

Comments
 (0)