Skip to content

Bug: Stale deliverables from prior runs bleed into new reports #257

@Vince-Cercury

Description

@Vince-Cercury

Bug Description

When running Shannon against the same target repo multiple times (separate runs, not resume), stale exploitation evidence files from prior runs are picked up by assembleReportActivity() and included in the new report — even when the current run's vulnerability analysis found nothing to exploit.

Root Cause

assembleFinalReport() in src/services/reporting.ts:19-77 reads whatever *_exploitation_evidence.md files exist in {repoPath}/deliverables/. It does not verify whether those files were produced by the current run. Since deliverables are saved to the target repo's filesystem, files from a previous run persist across runs.

The pipeline does not clean {repoPath}/deliverables/ at the start of a fresh (non-resume) workflow.

Reproduction

  1. Run Shannon against a target: ./shannon start URL=<url> REPO=my-repo
  2. Wait for completion (exploitation evidence files are written to repos/my-repo/deliverables/)
  3. Fix one of the reported vulnerabilities in the target app
  4. Run Shannon again with a new workspace: ./shannon start URL=<url> REPO=my-repo
  5. Observe: the final report includes findings from Run 1 that the current run's vuln agent no longer flagged

Observed Impact

In a real case with two independent runs against the same target (run-zagg-app_shannon-1774435299398 on March 25, run-zagg-app_shannon-1774524842573 on March 26):

  • Run 2's injection-vuln agent produced an empty exploitation queue ({"vulnerabilities": []})
  • injection-exploit agent correctly never ran (not present in session.json)
  • However, Run 1's injection_exploitation_evidence.md was still in the repo's deliverables/ folder
  • assembleReportActivity() concatenated it into the final report
  • 2 out of 9 findings in the new report were stale (INJ-VULN-PATH-TRAVERSAL, INJ-VULN-05), carried over verbatim from Run 1

Expected Behavior

A fresh (non-resume) run should only include findings from the current run. Stale deliverables from prior runs should not appear in the report.

Suggested Fix

Clear {repoPath}/deliverables/ at the start of a new workflow (but not on resume). The distinction already exists in the workflow — loadResumeState() is only called when resuming.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions