Tales-Cunha commited on
Commit
2eb19c1
·
1 Parent(s): 0579f2b

docs: add readme and change the foundryRunner

Browse files
src/agents/tester/README.md ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Agente Gerador de PoCs (Tester)
2
+
3
+ Este agente é responsável por validar vulnerabilidades identificadas pelo **Agente Auditor** através da geração automática de exploits em Solidity (*Proof of Concepts* - PoCs) e execução em um ambiente sandbox utilizando **Foundry**.
4
+
5
+ ## 1. Visão Geral
6
+
7
+ O agente implementa um **loop ReAct** (Gerar → Executar → Refletir) orquestrado via **LangGraph**. Diferente de abordagens tradicionais, ele utiliza um componente **Oracle** para preparar o scaffold do teste, permitindo que o LLM foque exclusivamente na lógica do exploit.
8
+
9
+ ### Fluxo Multi-agente
10
+ ```mermaid
11
+ graph LR
12
+ Coder[Agente Gerador] -- "Código Fonte" --> Auditor
13
+ Auditor[Agente Auditor] -- "Findings (JSON)" --> Tester
14
+ Tester[Agente de PoCs] -- "PoCResult (Verificado)" --> Final[Projeto Validado]
15
+ ```
16
+
17
+ ### Principais Funcionalidades:
18
+ - **Sandbox Autônomo:** O agente detecta e inicializa o ambiente Foundry (`/tmp/poc-sandbox`) automaticamente no primeiro uso.
19
+ - **Scaffold Automático:** Gera o arquivo `Exploit.t.sol` com o contrato vítima já instanciado e financiado.
20
+ - **Loop de Auto-correção:** Se o exploit falhar, o agente analisa os logs e tenta corrigir o código por até 5 iterações.
21
+ - **Integração com DeepSeek:** Utiliza o modelo `deepseek-v4-pro` via OpenRouter.
22
+
23
+ ## 2. Arquitetura
24
+
25
+ O fluxo de execução segue o grafo definido em `agent.ts`:
26
+
27
+ 1. **Oracle Node:** Recebe o relatório de vulnerabilidade e gera o scaffold Solidity inicial.
28
+ 2. **Generate PoC Node:** O LLM completa a função `test_Exploit()` com base no scaffold e na descrição da falha.
29
+ 3. **Run Foundry Node:** Escreve o código no sandbox e executa `forge test`.
30
+ 4. **Reflect Node:** Em caso de falha, analisa o output do Forge, classifica o erro e fornece feedback para o próximo ciclo de geração.
31
+
32
+ ## 3. Estrutura de Arquivos
33
+
34
+ ```
35
+ src/agents/tester/
36
+ ├── agent.ts # Definição do grafo LangGraph e lógica dos nodes
37
+ ├── state.ts # Estado interno do agente (PoCStateAnnotation)
38
+ ├── types.ts # Interfaces de entrada (Finding) e saída (PoCResult)
39
+ ├── index.ts # Entry point público (runPoCGenerator)
40
+
41
+ ├── tools/
42
+ │ ├── scaffoldGenerator.ts # Gerador de boilerplate Foundry
43
+ │ └── foundryRunner.ts # Executor de comandos shell (forge)
44
+
45
+ ├── prompts/
46
+ │ └── system.ts # Instruções especializadas para o LLM
47
+
48
+ └── utils/
49
+ ├── extractSolidity.ts # Parser de blocos de código
50
+ └── logAnalyzer.ts # Classificador de erros de execução
51
+ ```
52
+
53
+ ## 4. Integração e Uso
54
+
55
+ ### Fluxo de Dados (Input/Output)
56
+
57
+ O agente recebe um objeto `VulnerabilityReport`. Como o **Agente Auditor** gera objetos do tipo `Finding`, é necessário realizar um mapeamento (veja `src/index.ts` para o adapter).
58
+
59
+ #### Estrutura de Entrada (`VulnerabilityReport`)
60
+ ```typescript
61
+ interface VulnerabilityReport {
62
+ id: string; // Identificador único do report
63
+ severity: string; // "high", "medium", "low"
64
+ title: string; // Título curto da falha
65
+ description: string; // Descrição técnica detalhada
66
+ affectedContract: {
67
+ name: string; // Nome da classe do contrato
68
+ sourceCode: string; // Código-fonte completo (Solidity)
69
+ };
70
+ attackVector: string; // Descrição do caminho de ataque
71
+ exploitablePaths?: string[]; // (Opcional) Passos detalhados
72
+ }
73
+ ```
74
+
75
+ #### Estrutura de Saída (`PoCResult`)
76
+ ```typescript
77
+ interface PoCResult {
78
+ reportId: string;
79
+ status: "success" | "failed" | "timeout";
80
+ solidityCode: string; // Conteúdo final do Exploit.t.sol
81
+ executionLogs: string[]; // Logs brutos de todas as iterações
82
+ iterations: number; // Total de tentativas realizadas
83
+ }
84
+ ```
85
+
86
+ ### Exemplo de Integração
87
+ ```typescript
88
+ import { runPoCGenerator } from "./src/agents/tester";
89
+
90
+ // O orquestrador mapeia o Finding + Código Fonte para o Report
91
+ const result = await runPoCGenerator(report);
92
+ ```
93
+
94
+ ### Pré-requisitos
95
+ - **Foundry:** `forge` deve estar instalado e acessível. O agente busca em `~/.foundry/bin` e no PATH padrão.
96
+ - **API Key:** `OPENROUTER_API_KEY` deve estar configurada no arquivo `.env`.
97
+
98
+ ## 5. Avaliação de Resultados
99
+
100
+ O `PoCResult` retorna um status que indica a validade da vulnerabilidade ou a eficácia de um patch:
101
+
102
+ | Status | Significado | Ação Recomendada |
103
+ | :--- | :--- | :--- |
104
+ | **`success`** | Exploit executou e passou na assertion. | Vulnerabilidade confirmada. |
105
+ | **`failed`** | Exploit falhou após 5 tentativas. | Verificar `executionLogs` para erro de lógica ou compilação. |
106
+ | **`timeout`** | Forge excedeu 60 segundos. | Possível loop infinito no contrato ou exploit. |
107
+
108
+ ## 6. Base Acadêmica
109
+ A implementação deste agente foi inspirada no framework **PoCo** (Bergman et al., KTH 2025), adaptada para execução local determinística e suporte multi-agente.
src/agents/tester/tools/foundryRunner.ts CHANGED
@@ -1,6 +1,7 @@
1
  import { exec } from "child_process";
2
  import { promisify } from "util";
3
- import { writeFile } from "fs/promises";
 
4
 
5
  const execAsync = promisify(exec);
6
  const SANDBOX = "/tmp/poc-sandbox";
@@ -14,7 +15,22 @@ export interface FoundryResult {
14
  timedOut: boolean;
15
  }
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  export async function runFoundry(solidityCode: string): Promise<FoundryResult> {
 
 
18
  // Escrever o arquivo no sandbox
19
  await writeFile(`${SANDBOX}/test/Exploit.t.sol`, solidityCode, "utf-8");
20
 
 
1
  import { exec } from "child_process";
2
  import { promisify } from "util";
3
+ import { writeFile, access } from "fs/promises";
4
+ import { join } from "path";
5
 
6
  const execAsync = promisify(exec);
7
  const SANDBOX = "/tmp/poc-sandbox";
 
15
  timedOut: boolean;
16
  }
17
 
18
+ /**
19
+ * Garante que o sandbox Foundry existe e está inicializado.
20
+ */
21
+ async function ensureSandbox() {
22
+ try {
23
+ await access(join(SANDBOX, "foundry.toml"));
24
+ } catch {
25
+ console.log("[foundryRunner] Sandbox não encontrado. Inicializando...");
26
+ // Caminho absoluto para o script de setup (assume execução da raiz do projeto)
27
+ await execAsync("./scripts/setup-sandbox.sh");
28
+ }
29
+ }
30
+
31
  export async function runFoundry(solidityCode: string): Promise<FoundryResult> {
32
+ await ensureSandbox();
33
+
34
  // Escrever o arquivo no sandbox
35
  await writeFile(`${SANDBOX}/test/Exploit.t.sol`, solidityCode, "utf-8");
36