Skip to content

Audit Stage

The audit stage inspects planned components for security vulnerabilities and emits raw findings. It has two concrete strategy implementations. The orchestrator selects one from ScanExecution.audit_strategy.

Location

src/stages/audit/

Stage class hierarchy

BaseAuditStage                    (src/stages/audit/stage.py)
  ├── DefaultAuditStage               strategy = "default"
  └── VariantAnalysisAuditStage       strategy = "variant_analysis"
class BaseAuditStage(BaseStage[StageInput, StageOutput]):
    name = StageName.AUDIT
    strategy: ClassVar[str]
    required_artifacts = ("source_snapshot", "plan_artifact", "threat_model")
    produced_artifacts = ("raw_findings", "audit_component_state")

Strategy selection

ScanExecution.audit_strategy Concrete class
"default" / "component" DefaultAuditStage
"variant_analysis" / "variant" VariantAnalysisAuditStage

DefaultAuditStage

Audits planned components in parallel. For each component:

  1. Builds an audit prompt from:
  2. The base template (stages/audit/prompts/default.txt)
  3. Plan component scope (files/paths)
  4. Threat model artifact context
  5. Plugin prompt sections (context.plugins.plugin.build_prompt_sections(...))
  6. Plugin schema overrides applied to schemas/findings.json
  7. PR review focus block (if metadata["pr_review"] is present)
  8. Runs an agent task (purpose="audit.default") for each component.
  9. Parses structured findings from agent output using the effective schema.
  10. Emits finding_updated for each parsed finding.
  11. After all components: writes vega.raw_findings and vega.audit_component_state artifacts.
  12. Emits raw_findings_ready.

Parallelism

Component work runs in a thread pool controlled by RunPolicy.max_workers_per_runner. The default is 1 (sequential). Set VEGA_MAX_WORKERS_PER_RUNNER or VEGA_CORE_AUDIT_WORKERS_MAX for parallel execution.

Audit resume

When execution.audit_resume_artifact is provided with execution.audit_resume_policy="skip_completed":

  1. Loads the saved vega.audit_component_state artifact.
  2. Components marked as completed in that artifact are skipped.
  3. Their findings are carried forward into the new raw_findings artifact.
  4. Only pending or failed components are re-audited.

This supports partial scan recovery and multi-shard scan orchestration.

Component sharding

execution.assigned_component_ids restricts audit to specific component ids. execution.audit_shard_id tags the shard for artifact naming. Backend uses this to split a large repository's audit across multiple runner containers.

VariantAnalysisAuditStage

A specialized strategy for variant analysis — searching for similar patterns of a known vulnerability class across the codebase. Requires ScanIntent.variant_context to be set. Uses stages/audit/prompts/variant_analysis.txt and focuses agent prompts on the known pattern.

Finding schema

The agent produces structured findings validated against stages/audit/schemas/findings.json. Each finding includes:

{
  "finding_id": "unique-id",
  "title": "Vulnerability title",
  "description": "Detailed description",
  "severity": "critical | high | medium | low | info",
  "bug_class": "...",
  "file_path": "src/service.py",
  "line_start": 42,
  "line_end": 55,
  "component_id": "auth/login_handler",
  "evidence": ["relevant code snippet"],
  "attacker_profile": "...",
  "required_state": "...",
  "required_services": "..."
}

Plugins can override enum values for bug_class, attacker_profile, required_state, and required_services through StagePlugin.output_schema_overrides(...). See Plugin System for details.

Domain events

Event kind When emitted
component_worker_started Component audit begins
component_worker_completed Component audit finishes
component_worker_failed Component agent call fails
component_worker_cancelled Component cancelled
component_worker_skipped Component skipped (resume)
finding_updated Each parsed finding
raw_findings_ready All components processed

finding_updated payload

The event carries the full canonical finding object. Key fields:

{
  "finding_id": "run123:auth:login_handler:finding-1",
  "bug_id": "...",
  "title": "src/auth/login.py: Missing authorization check",
  "bug_title": "Missing authorization check",
  "blame_path": "src/auth/login.py",
  "bug_class": "broken_auth",
  "category": "broken_auth",
  "summary": "...",
  "bug_description": "...",
  "affected_paths": ["src/auth/login.py"],
  "severity": "high",
  "likelihood": "high",
  "confidence": "high",
  "threat_model_similarity": "medium",
  "attacker_profile": "...",
  "required_state": "...",
  "required_services": [],
  "status": "candidate",
  "root_cause": "...",
  "root_cause_sections": {"overview": "...", "analysis": "...", "attack_vector": {...}},
  "buggy_locations": [{"file_path": "...", "location_kind": "sink", ...}],
  "evidence": ["..."],
  "suggested_fix": "...",
  "source_stage": "audit",
  "source_strategy": "default",
  "component_id": "auth:login_handler",
  "component_name": "login_handler",
  "module_name": "auth",
  "metadata": {...}
}

Backend persists findings from this event. The finding_id is stable across partial scans of the same component.

Deduplication

Raw findings from all scan runners flow into SharedTriageService via ScanTransition.apply_output(...) after the audit stage completes. See Findings & Triage.

Artifact outputs

Artifact kind Content
vega.raw_findings All raw agent findings across all components
vega.audit_component_state Per-component status (pending/completed/failed) for resume

Cancellation

BaseAuditStage uses context.checkpoint(StageName.AUDIT, progress) at component boundaries. When cancellation is requested, in-flight agent calls are cancelled via context.cancellation.cancel_active_agent_calls(), and a stage_cancelled event is emitted with the current progress.

Error handling

Condition Behavior
Single component agent failure Component marked failed; audit continues
All components fail Stage fails with audit_all_components_failed
Agent timeout (per-stage) StageError(code="audit_timeout", retryable=True)
Schema parse failure Finding skipped; warning emitted