diff --git a/prompts/pipeline-testing/report-executive.txt b/prompts/pipeline-testing/report-executive.txt index a735045..bd62c67 100644 --- a/prompts/pipeline-testing/report-executive.txt +++ b/prompts/pipeline-testing/report-executive.txt @@ -2,34 +2,4 @@ # This section above is metadata and not part of the prompt. === PROMPT === -Create a file at `deliverables/comprehensive_security_assessment_report.md` with this content: - -```markdown -# Injection Exploitation Evidence - -## Successfully Exploited Vulnerabilities - -### INJ-VULN-01: SQL Injection Test - -**Summary:** Test SQL injection vulnerability for pipeline testing. - -# Authentication Exploitation Evidence - -## Successfully Exploited Vulnerabilities - -### AUTH-VULN-01: Authentication Bypass Test - -**Summary:** Test authentication vulnerability for pipeline testing. -``` - -Then read and modify the file by adding these sections at the top: - -1. **Executive Summary** section with: - - Target: {{WEB_URL}} - - Assessment Date: (current date) - - Scope: Authentication, XSS, SQL and Command Injection, SSRF, Authorization testing - - Brief summary of findings (2-3 vulnerabilities found for testing) - -2. **Network Reconnaissance** section with test data for open ports and services - -Save the modified content back to `deliverables/comprehensive_security_assessment_report.md`, then say "Done". \ No newline at end of file +Read `deliverables/comprehensive_security_assessment_report.md`, prepend "# Security Assessment Report\n\n**Target:** {{WEB_URL}}\n\n" to the content, and save it back. Say "Done". diff --git a/src/phases/reporting.ts b/src/phases/reporting.ts index 0b5fc7c..7ea28d5 100644 --- a/src/phases/reporting.ts +++ b/src/phases/reporting.ts @@ -48,9 +48,12 @@ export async function assembleFinalReport(sourceDir: string): Promise { } const finalContent = sections.join('\n\n'); - const finalReportPath = path.join(sourceDir, 'deliverables', 'comprehensive_security_assessment_report.md'); + const deliverablesDir = path.join(sourceDir, 'deliverables'); + const finalReportPath = path.join(deliverablesDir, 'comprehensive_security_assessment_report.md'); try { + // Ensure deliverables directory exists + await fs.ensureDir(deliverablesDir); await fs.writeFile(finalReportPath, finalContent); console.log(chalk.green(`✅ Final report assembled at ${finalReportPath}`)); } catch (error) { diff --git a/src/temporal/activities.ts b/src/temporal/activities.ts index 15df935..c2b2dc7 100644 --- a/src/temporal/activities.ts +++ b/src/temporal/activities.ts @@ -58,6 +58,7 @@ import { rollbackGitWorkspace, getGitCommitHash, } from '../utils/git-manager.js'; +import { assembleFinalReport } from '../phases/reporting.js'; import { getPromptNameForAgent } from '../types/agents.js'; import { AuditSession } from '../audit/index.js'; import type { AgentName } from '../types/agents.js'; @@ -305,3 +306,19 @@ export async function runAuthzExploitAgent(input: ActivityInput): Promise { return runAgentActivity('report', input); } + +/** + * Assemble the final report by concatenating exploitation evidence files. + * This must be called BEFORE runReportAgent to create the file that the report agent will modify. + */ +export async function assembleReportActivity(input: ActivityInput): Promise { + const { repoPath } = input; + console.log(chalk.blue('📝 Assembling deliverables from specialist agents...')); + try { + await assembleFinalReport(repoPath); + } catch (error) { + const err = error as Error; + console.log(chalk.yellow(`⚠️ Error assembling final report: ${err.message}`)); + // Don't throw - the report agent can still create content even if no exploitation files exist + } +} diff --git a/src/temporal/workflows.ts b/src/temporal/workflows.ts index c07289c..700dc57 100644 --- a/src/temporal/workflows.ts +++ b/src/temporal/workflows.ts @@ -167,6 +167,11 @@ export async function pentestPipelineWorkflow( // === Phase 5: Reporting === state.currentPhase = 'reporting'; state.currentAgent = 'report'; + + // First, assemble the concatenated report from exploitation evidence files + await acts.assembleReportActivity(activityInput); + + // Then run the report agent to add executive summary and clean up state.agentMetrics['report'] = await acts.runReportAgent(activityInput); state.completedAgents.push('report');