Skip to content

Commit 063b475

Browse files
committed
Adding file path + exploit scenario part
1 parent a636871 commit 063b475

4 files changed

Lines changed: 36 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Different is a variant-analysis agentic tool built with DeepAgents. It does two
99

1010
The logic is agentic: an LLM calls local Git tools (and optional GitHub API tools) in a loop to inspect commits, diffs, and related PR/issue context.
1111

12+
Each finding includes `id`, `kind`, `severity`, `title`, `root_cause`, `fix_summary`, `evidence`, and `tags`. For `kind="bug"` findings with a concrete severity (not `"unknown"`), it also includes `main_file` and `exploit_risk` (a short paragraph describing how an attacker could exploit the bug and what impact they could get).
13+
1214
The inspiration agent can fetch PR labels and review comments for richer context. The target agent can search commit messages (`git_log_search`) to check if a fix was already applied, and list tracked files (`git_ls_files`) to explore the project structure.
1315

1416
## When to use it

src/different_agent/agents.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from langchain.agents.structured_output import AutoStrategy
77
from langchain_core.language_models import BaseChatModel
88
from langgraph.cache.base import BaseCache
9-
from pydantic import BaseModel, Field
9+
from pydantic import BaseModel, Field, model_validator
1010

1111
from different_agent.git_tools import (
1212
ast_grep,
@@ -28,7 +28,7 @@
2828
github_recent_prs,
2929
)
3030

31-
FINDING_SCHEMA_VERSION = "v1"
31+
FINDING_SCHEMA_VERSION = "v3"
3232

3333

3434
class EvidenceCommit(BaseModel):
@@ -49,11 +49,25 @@ class Finding(BaseModel):
4949
kind: Literal["bug", "vulnerability", "hardening"]
5050
title: str
5151
severity: Literal["low", "medium", "high", "critical", "unknown"]
52+
main_file: str | None = None
53+
exploit_risk: str | None = None
5254
root_cause: str
5355
fix_summary: str
5456
evidence: FindingEvidence
5557
tags: list[str] = Field(default_factory=list)
5658

59+
@model_validator(mode="after")
60+
def _require_bug_risk_fields(self) -> Finding:
61+
if self.kind != "bug" or self.severity == "unknown":
62+
return self
63+
if not self.main_file:
64+
raise ValueError("main_file is required for kind='bug' with severity!='unknown'")
65+
if not self.exploit_risk or not self.exploit_risk.strip():
66+
raise ValueError("exploit_risk is required for kind='bug' with severity!='unknown'")
67+
if self.exploit_risk.strip().lower() in {"low", "medium", "high", "critical", "unknown"}:
68+
raise ValueError("exploit_risk must be a short paragraph, not a keyword")
69+
return self
70+
5771

5872
class FindingsResponse(BaseModel):
5973
findings: list[Finding]
@@ -105,6 +119,9 @@ class TargetAssessmentsResponse(BaseModel):
105119
- Do NOT paste entire diffs into the JSON. Keep diff_snippets short.
106120
- If you include GitHub issues/PRs, include their links in evidence.links.
107121
- Be conservative: if you can't justify severity, set severity="unknown".
122+
- If kind="bug" and severity!="unknown":
123+
- main_file must be set to the single most relevant file path for the fix (usually pick 1 entry from evidence.files_changed).
124+
- exploit_risk must be a short paragraph explaining how an attacker could exploit the bug and what they could gain (preconditions + impact). Keep it similar length to root_cause/fix_summary.
108125
- root_cause must describe the generalized mechanism (unsafe pattern + conditions), not just the local symbol name.
109126
- fix_summary must describe the conceptual mitigation, not only the exact code change.
110127
- tags should include short idea-level keywords to help variant matching (e.g. "ambiguous-encoding",
@@ -120,6 +137,8 @@ class TargetAssessmentsResponse(BaseModel):
120137
- kind ("bug" | "vulnerability" | "hardening")
121138
- title (string)
122139
- severity ("low" | "medium" | "high" | "critical" | "unknown")
140+
- main_file (string|null) # required when kind="bug" and severity!="unknown"
141+
- exploit_risk (string|null) # required when kind="bug" and severity!="unknown"
123142
- root_cause (string)
124143
- fix_summary (string)
125144
- evidence {{

src/different_agent/report.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ def render_findings_html(findings: list[dict]) -> str:
1717
now = datetime.now(UTC).replace(microsecond=0).isoformat()
1818
rows = []
1919
for f in findings:
20+
kind = f.get("kind")
21+
severity = f.get("severity")
22+
show_risk_fields = kind == "bug" and severity not in (None, "", "unknown")
23+
main_file = f.get("main_file") if show_risk_fields else ""
24+
exploit_risk = f.get("exploit_risk") if show_risk_fields else ""
2025
rows.append(
2126
"<tr>"
2227
f"<td>{_safe_json(f.get('id'))}</td>"
@@ -25,6 +30,8 @@ def render_findings_html(findings: list[dict]) -> str:
2530
f"<td>{_safe_json(f.get('title'))}</td>"
2631
f"<td><pre>{_safe_json(f.get('root_cause'))}</pre></td>"
2732
f"<td><pre>{_safe_json(f.get('fix_summary'))}</pre></td>"
33+
f"<td>{_safe_json(main_file)}</td>"
34+
f"<td><pre>{_safe_json(exploit_risk)}</pre></td>"
2835
"</tr>"
2936
)
3037

@@ -58,6 +65,8 @@ def render_findings_html(findings: list[dict]) -> str:
5865
<th>title</th>
5966
<th>root_cause</th>
6067
<th>fix_summary</th>
68+
<th>main_file</th>
69+
<th>exploit_risk</th>
6170
</tr>
6271
</thead>
6372
<tbody>

tests/test_report.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ def test_render_findings_html_escapes_values() -> None:
1010
"kind": "bug",
1111
"severity": "high",
1212
"title": "Title & stuff",
13+
"main_file": "src/<main>.py",
14+
"exploit_risk": "<high>",
1315
"root_cause": "a < b",
1416
"fix_summary": "use & sanitize",
1517
}
@@ -18,6 +20,8 @@ def test_render_findings_html_escapes_values() -> None:
1820
assert "Findings" in html
1921
assert "&lt;f-1&gt;" in html
2022
assert "Title &amp; stuff" in html
23+
assert "src/&lt;main&gt;.py" in html
24+
assert "&lt;high&gt;" in html
2125
assert "a &lt; b" in html
2226
assert "use &amp; sanitize" in html
2327

0 commit comments

Comments
 (0)