Spaces:
Runtime error
Runtime error
File size: 2,906 Bytes
4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 4e2e30e 3f143e9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | import type { VulnerabilityReport } from "../agents/tester/types.js";
/**
* Maps a Finding from the Auditor to a VulnerabilityReport for the Tester.
* Enriches the description with all available auditor context:
* judge review, recommendation, exploit paths — giving the tester
* maximum information to generate a precise, specific PoC.
*/
export function mapFindingToReport(
finding: any,
sourceCode: string,
repoContext?: string
): VulnerabilityReport {
const title = finding.title || "Unknown vulnerability";
const nameMatch = finding.path?.match(/([^\/]+)\.sol$/);
const contractName = nameMatch ? nameMatch[1] : "TargetContract";
const exploitablePaths: string[] = finding.judgeReview?.exploitablePaths || [];
// Build a rich description combining all auditor context
const descriptionParts: string[] = [
finding.description || "No description provided by auditor.",
];
if (finding.judgeReview?.review) {
descriptionParts.push(`\n## Judge Analysis\n${finding.judgeReview.review}`);
}
if (finding.recommendation) {
descriptionParts.push(`\n## Recommended Fix\n${finding.recommendation}`);
}
if (exploitablePaths.length > 0) {
descriptionParts.push(`\n## Exploit Paths (step-by-step)\n${exploitablePaths.map((p, i) => `${i + 1}. ${p}`).join("\n")}`);
}
if (repoContext) {
descriptionParts.push(`\n## Protocol Context\n${repoContext.slice(0, 1500)}`);
}
// Infer vulnerability type from title/description when auditor doesn't provide one
const inferType = (): string => {
const text = `${title} ${finding.description || ""}`.toLowerCase();
if (text.includes("reentr")) return "reentrancy";
if (text.includes("access control") || text.includes("unauthorized")) return "access control";
if (text.includes("overflow") || text.includes("underflow")) return "arithmetic";
if (text.includes("flash loan")) return "flash loan";
if (text.includes("oracle") || text.includes("price manipul")) return "oracle manipulation";
if (text.includes("denial of service") || text.includes("dos")) return "denial of service";
if (text.includes("front.run") || text.includes("sandwich")) return "front-running";
return "logic error";
};
const severity = ["critical", "high", "medium", "low"].includes(finding.severity)
? finding.severity
: "medium";
return {
id: title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 50),
severity: severity as VulnerabilityReport["severity"],
type: inferType(),
title,
description: descriptionParts.join("\n"),
affectedContract: {
name: contractName,
sourceCode,
sourceFilePath: finding.path,
},
attackVector: exploitablePaths[0] ?? finding.description?.slice(0, 120) ?? "Unknown",
exploitablePaths,
codeSnippet: finding.codeSnippet,
location: finding.location,
suggestedCheatcodes: [],
};
}
|