Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ymir/agents/prompts/backport/instructions.j2
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ a backport that won't actually fix the shipped RPM.
PatchN: <PACKAGE>-<VERSION>-<CVE_ID>.patch
where <VERSION> is the upstream version from the spec file's Version field.

1. Knowing Jira issue <JIRA_ISSUE>, CVE ID <CVE_ID> or both, use the `git_log_search` tool to check
in the dist-git repository whether the issue/CVE has already been resolved. If it has,
1. Knowing Jira issue <JIRA_ISSUE>, CVE ID(s) <CVE_ID> or both, use the `git_log_search` tool to check
in the dist-git repository whether each issue/CVE has already been resolved. If it has,
end the process with `success=True` and `status="Backport already applied"`.
Note: <CVE_ID> may contain multiple CVE IDs when the Jira issue covers multiple CVEs.
The `git_log_search` tool handles multiple CVE IDs automatically.

2. Use the `git_prepare_package_sources` tool to prepare package sources in directory <UNPACKED_SOURCES>
for application of the upstream patch.
Expand Down
6 changes: 4 additions & 2 deletions ymir/agents/prompts/backport/instructions_zstream.j2
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ a backport that won't actually fix the shipped RPM.
Do NOT add comments above the Patch tag for z-stream branches unless
existing patches in the spec already use comments (see Priority 2).

1. Knowing Jira issue <JIRA_ISSUE>, CVE ID <CVE_ID> or both, use the `git_log_search` tool to check
in the dist-git repository whether the issue/CVE has already been resolved. If it has,
1. Knowing Jira issue <JIRA_ISSUE>, CVE ID(s) <CVE_ID> or both, use the `git_log_search` tool to check
in the dist-git repository whether each issue/CVE has already been resolved. If it has,
end the process with `success=True` and `status="Backport already applied"`.
Note: <CVE_ID> may contain multiple CVE IDs when the Jira issue covers several CVEs.
The `git_log_search` tool handles multiple CVE IDs automatically.

2. Use the `git_prepare_package_sources` tool to prepare package sources in directory <UNPACKED_SOURCES>
for application of the upstream patch.
Expand Down
8 changes: 8 additions & 0 deletions ymir/agents/prompts/triage/output_format.j2
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Backport resolution:
}
}
```
Note: When the Jira issue covers multiple CVEs, include ALL CVE IDs in `cve_id`, e.g.:
`"cve_id": "CVE-1234-98765 CVE-1234-98766"`

Rebase resolution:
```json
Expand All @@ -36,6 +38,8 @@ Rebase resolution:
}
}
```
Note: When the Jira issue covers multiple CVEs, include ALL CVE IDs in `cve_id`, e.g.:
`"cve_id": "CVE-1234-98765 CVE-1234-98766"`

Rebuild resolution:
```json
Expand All @@ -53,6 +57,8 @@ Rebuild resolution:
}
}
```
Note: When the Jira issue covers multiple CVEs, include ALL CVE IDs in `cve_id`, e.g.:
`"cve_id": "CVE-1234-98765 CVE-1234-98766"`

Postponed resolution (rebuild waiting for dependency):
```json
Expand All @@ -70,6 +76,8 @@ Postponed resolution (rebuild waiting for dependency):
}
}
```
Note: When the Jira issue covers multiple CVEs, include ALL CVE IDs in `cve_id`, e.g.:
`"cve_id": "CVE-1234-98765 CVE-1234-98766"`

Not-affected resolution (CVE does not apply):
```json
Expand Down
6 changes: 4 additions & 2 deletions ymir/agents/prompts/triage/prompt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,10 @@ You must decide between one of the following actions. Follow these guidelines to
* The code changes address the specific vulnerability type
(buffer overflow, integer overflow, etc.)
* The affected functions/files align with the CVE details
- **WARNING**: Patches from bundled CVE updates (e.g., Oracle CPU, bundled library updates)
may fix MULTIPLE CVEs - verify you have the correct patch for THIS specific CVE
- **Multiple CVEs in one issue**: When the Jira issue covers multiple CVEs,
verify you have the correct patches for ALL of them — not just one.
Include ALL CVE IDs in the `cve_id` output field so the downstream
backport agent knows the full scope and applies all related patches.
- If you cannot confirm the patch matches the CVE, search for alternative patches or
request clarification
* Only proceed with URLs that contain valid patch content AND address the specific issue
Expand Down
10 changes: 8 additions & 2 deletions ymir/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ class BackportInputSchema(BaseModel):
package: str = Field(description="Package to update")
dist_git_branch: str = Field(description="Git branch in dist-git to be updated")
jira_issue: str = Field(description="Jira issue to reference as resolved")
cve_id: str | None = Field(default=None, description="CVE ID if the jira issue is a CVE")
cve_id: str | None = Field(
default=None,
description="CVE ID(s) if the jira issue is a CVE; may contain multiple CVE IDs",
)
upstream_patches: list[str] = Field(
description="List of URLs to upstream patches that were validated using the get_patch_from_url tool"
)
Expand Down Expand Up @@ -241,7 +244,10 @@ class BackportData(BaseModel):
"Do NOT repeat the justification rationale here.",
)
jira_issue: str = Field(description="Jira issue identifier")
cve_id: str | None = Field(description="CVE identifier", default=None)
cve_id: str | None = Field(
description="CVE identifier(s); include ALL CVE IDs when the issue covers multiple CVEs",
default=None,
)
fix_version: str | None = Field(description="Fix version in Jira (e.g., 'rhel-9.8')", default=None)


Expand Down
10 changes: 10 additions & 0 deletions ymir/tools/unprivileged/tests/unit/test_wicked_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@ async def test_git_patch_creation_tool_with_hideous_patch_file(git_repo, tmp_pat
("CVE-2025-12346", "", "No matches found for 'CVE-2025-12346'"),
("", "RHEL-123456", "Found 1 matching commit(s) for 'RHEL-123456'"),
("", "RHEL-123457", "No matches found for 'RHEL-123457'"),
(
"CVE-2025-12345 CVE-2025-99999",
"",
"Found 1 matching commit(s) for 'CVE-2025-12345, CVE-2025-99999'",
),
Comment thread
antbob marked this conversation as resolved.
(
"CVE-2025-99998, CVE-2025-99999",
"",
"No matches found for 'CVE-2025-99998, CVE-2025-99999'",
),
],
)
async def test_git_log_search_tool_found(git_repo, cve_id, jira_issue, expected):
Expand Down
27 changes: 15 additions & 12 deletions ymir/tools/unprivileged/wicked_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from ymir.common.version_utils import parse_branch_name
from ymir.tools.base import CloneableTool as Tool

# Pattern to extract CVE IDs. Needs to handles space-separated, comma-separated,
# or any other separator as there is no standard in how those can be provided.
CVE_ID_PATTERN = re.compile(r"CVE-\d{4}-\d{4,}")


class GitPreparePackageSourcesInput(BaseModel):
unpacked_sources_path: AbsolutePath = Field(
Expand Down Expand Up @@ -541,7 +545,7 @@ async def _run(

class GitLogSearchToolInput(BaseModel):
repository_path: AbsolutePath = Field(description="Absolute path to the git repository")
cve_id: str = Field(description="CVE ID to look for in git history")
cve_id: str = Field(description="CVE ID(s) to look for in git history (may contain multiple CVE IDs)")
jira_issue: str = Field(description="Jira issue to look for in git history")


Expand Down Expand Up @@ -571,24 +575,23 @@ async def _run(

if not (repo_path / ".git").exists():
raise ToolError(f"Not a git repository: {repo_path}")
search = tool_input.cve_id or tool_input.jira_issue
if not search:
cve_ids = CVE_ID_PATTERN.findall(tool_input.cve_id) if tool_input.cve_id else []
search_terms = cve_ids or ([tool_input.jira_issue] if tool_input.jira_issue else [])
if not search_terms:
raise ToolError("No search string provided, jira_issue or cve_id is required")

cmd = [
"git",
"log",
"--no-merges",
f"--grep={search}",
"-n",
"1",
"--pretty=%s %H",
]
cmd = ["git", "log", "--no-merges"]
for term in search_terms:
cmd.extend(["--grep", term])
if cve_ids and tool_input.jira_issue:
cmd.extend(["--grep", tool_input.jira_issue])
cmd.extend(["-n", "1", "--pretty=%s %H"])

exit_code, stdout, stderr = await run_subprocess(cmd, cwd=repo_path)
if exit_code != 0:
raise ToolError(f"Git command failed: {stderr}")

search = ", ".join(search_terms)
output = (stdout or "").strip()
if not output:
return StringToolOutput(result=f"No matches found for '{search}'")
Expand Down
Loading