# Project export: SIFT Guardian: Self-Correcting SecOps Agents

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2026
- Tagline: An autonomous, self-correcting multi-agent incident response system that automatically critiques and adjusts its own forensic investigation loops to generate security advisory reports.
- Devpost: https://devpost.com/software/sift-guardian-self-correcting-secops-agents
- GitHub: https://github.com/sananmalik/SIFTGuardian.git
- Team: 1 GitHub contributor(s) — Sanan Malik (5 commits)

## Devpost submission (written by the team)

### Inspiration

Alert fatigue is one of the most critical issues facing modern Security Operations Centers (SOCs). Security analysts are constantly bombarded by logs, many of which are false alarms, while critical threats remain obscured due to missing forensic context. We wanted to build a system that mimics a real SecOps team—allowing specialized agents to not only analyze logs but also critique each other's work and automatically query the database for missing context, just like a human investigator would.

### What it does

SIFT Guardian is an autonomous SecOps incident response system. When a telemetry payload (like an encoded PowerShell script, a malicious Word document spawning child processes, or a web shell injection) is submitted: The Investigator Agent performs initial threat signature analysis. The Skeptic Agent audits the findings. If confidence is low or telemetry categories (like Parent Process, Persistence, or Network Activity) are missing, it triggers a self-correction loop. The Investigator automatically performs reanalysis, querying the enterprise log database for the missing logs. The Verifier Agent approves the findings against telemetry sources. The Reporter Agent compiles a comprehensive, peer-reviewed Markdown intelligence advisory report.

### How we built it

Backend: Built using C# on the latest .NET 10.0 SDK. We designed a decoupled transient/singleton dependency injection structure for specialized agent personas coordinated by a central AgentOrchestrator workflow manager. Frontend: Constructed with Vanilla HTML5, CSS3, and JavaScript (ES6). It features a glowing cyberpunk grid command-center theme with a real-time topology flow-graph illustrating active agent states and self-correction cycles, and a custom logs terminal.

### Challenges we ran into

Orchestrating agent collaboration dynamically without getting stuck in infinite loops. We solved this by developing structured context state maps that pass target feedback parameters (missing evidence classes) back to the investigator's reanalysis handler.

### Accomplishments we're proud of

Designing a visual dashboard that is highly premium and responsive, providing immediate visual feedback on multi-agent collaboration. Implementing a fully functional self-correcting logic loop that dynamically gathers additional forensic evidence on-the-fly.

### What we learned

We learned how to design contrasting agent personalities (a positive investigator vs. an aggressive skeptic) to achieve rigorous output validation that minimizes false positive rates.

### What's next

Integrating real-time SIEM connectors (Splunk/Elasticsearch). Enabling automated containment tasks (e.g. blocking IPs, isolating endpoints, or revoking OAuth tokens).

## README (from the GitHub repository)

# 🛡️ SIFT Guardian: Self-Correcting Multi-Agent Incident Response

SIFT Guardian is an advanced, autonomous Security Operations Center (SecOps) incident response system designed to automate forensic investigation and intelligence advisory compilation. Built for **UC Berkeley's AI Hackathon**, SIFT Guardian solves the challenge of alert fatigue and rigid automation by utilizing a cognitive, self-correcting multi-agent architecture.

---

## 🌟 The Core Problem & Our Solution
Modern SOC analysts are overwhelmed by security alerts. Traditional Security Orchestration, Automation, and Response (SOAR) playbooks are fragile, brittle, and unable to deal with ambiguity. When telemetry is incomplete, a human must manually dig through logs.

**SIFT Guardian** changes this. By orchestrating a team of specialized AI agents in a **self-correcting cognitive loop**, the system can:
1. Conduct initial analysis on telemetry payloads.
2. Critique its own findings using a skeptic agent that flags gaps in forensic evidence.
3. Automatically route back for reanalysis to pull missing logs (e.g. parent processes, persistence mechanisms, or network connections).
4. Verify the finalized evidence tree.
5. Compile and export a professional, peer-reviewed **Intelligence Advisory Report**.

---

## 🗺️ System Topology & Agent Architecture

SIFT Guardian implements a directed cognitive pipeline with an active feedback loop:

```mermaid
graph TD
    A[Case Intake / Telemetry Payload] --> B[Investigator Agent]
    B -->|Initial Finding & Confidence| C[Skeptic Agent]
    C -->|If Confidence < 80% & Evidence Missing| D[Self-Correction Loop]
    D -->|Request Missing Forensic Categories| B
    B -->|Reanalysis / Query Telemetry DB| C
    C -->|If Confidence >= 80% & Approved| E[Verifier Agent]
    E -->|Verify Telemetry Integrity| F[Reporter Agent]
    F -->|Compile Markdown Report| G[Intelligence Advisory Output]

    style D fill:#f59e0b,stroke:#d97706,stroke-width:2px,color:#fff
    style B fill:#00f0ff,stroke:#0891b2,stroke-width:2px,color:#000
    style C fill:#f59e0b,stroke:#d97706,stroke-width:2px,color:#000
    style E fill:#10b981,stroke:#059669,stroke-width:2px,color:#000
    style F fill:#a855f7,stroke:#7c3aed,stroke-width:2px,color:#000
```

### 🔍 Tactical Agents
*   **Investigator Agent:** Parses incoming payload data, detects threat classifications, and queries the enterprise telemetry database to retrieve detailed indicators of compromise (IoC).
*   **Skeptic Agent:** Acts as the Quality Assurance auditor. It challenges the initial analysis, checks for missing evidence categories (like Process Tree, Parent Process, Persistence, or Network Activity), and triggers the self-correction cycle if threshold standards are not met.
*   **Verifier Agent:** Inspects the gathered forensic evidence directly against the logging endpoints to approve credibility.
*   **Reporter Agent:** Formulates the peer-reviewed report into structured markdown, providing summaries, timeline flows, and actionable remediation steps.

---

## 🚀 Key Features

*   **Tactical Cyber-Defense Dashboard:** A beautiful command-center interface using a modern dark theme with custom scanline details.
*   **Dynamic Topology Map:** Live visual highlights illustrating which agent is active, including active loop indicators when the self-correction cycle is running.
*   **Real-time SecOps Terminal:** A simulated command-line output showing exact step-by-step logs and decision reasoning of each agent in color-coded lines.
*   **Advisory Export:** Quick button to export the finalized markdown file for local archival.
*   **Built-in Threat Profiles:** One-click loaders for common attack scenarios:
    *   *Suspicious PowerShell Execution* (Encoded command execution calling home).
    *   *Phishing Attachment Execution* (Word document spawning cmd and certutil).
    *   *IIS Web Shell Backdoor* (Web application process injecting ASPX shell).

---

## 💻 Tech Stack

*   **Backend:** ASP.NET Core Web API (.NET 10.0 C#)
*   **Frontend:** Vanilla HTML5, CSS3 (Tactical Grid & Glowing Glassmorphism), and JavaScript ES6.
*   **Design & Typography:** Space Grotesk (headers) & JetBrains Mono (monospaced logs).

---

## ⚙️ Project Setup & How to Run

### Prerequisites
*   [.NET 10.0 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)

### 1. Clone & Build
```bash
# Navigate to the project directory
cd SIFTGuardian

# Build the project
dotnet build
```

### 2. Run the Server
```bash
# Start the web server with the HTTP profile
dotnet run --launch-profile "http"
```

The application will launch on:
*   **URL:** `http://localhost:5049`

### 3. Open in Browser
Open `http://localhost:5049` in your web browser, choose one of the Threat Profiles (e.g. *PowerShell Execution*), and click **Deploy Tactical Agents** to witness the self-correcting orchestration in real-time.


## Detected evidence (automated analysis)

Indexed codebase: 40 recognized source files, 107 KB.
- C# (language) — detected in the code
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code

## Codebase structure (from repository index)

### Files (47 of 47)

```
.gitattributes
.gitignore
Agents/IAgent.cs
Agents/InvestigatorAgent.cs
Agents/ReportAgent.cs
Agents/SkepticAgent.cs
Agents/VerifierAgent.cs
appsettings.Development.json
appsettings.json
Controllers/InvestigationController.cs
Models/AgentLog.cs
Models/AgentResponse.cs
Models/Finding.cs
Models/InvestigationCase.cs
Models/InvestigationResult.cs
Program.cs
Properties/launchSettings.json
README.md
Reports/report-10a5fe3c-50de-45f2-bee7-695ab6766689.md
Reports/report-22837a7f-43e1-4505-a1ad-dcf0a69452b1.md
Reports/report-2754c17e-0c6c-43aa-9a53-bf8d17af3a73.md
Reports/report-31b64152-e295-4ea0-8ee9-a5a3f6e51a54.md
Reports/report-3bf043bb-9f4b-4cb9-8579-1749c7fbadc8.md
Reports/report-42e17029-8b70-461a-a9f5-fa7cdba3c14c.md
Reports/report-4c540e8f-11c0-401a-9edf-367ce862865e.md
Reports/report-5a9330b0-bf8a-4026-8655-4eed3ddac8a0.md
Reports/report-5d87d4ec-3aef-4ca3-8b84-415748b160a9.md
Reports/report-85625ba0-65f2-42f3-bf8b-309cf38255e5.md
Reports/report-a195d8dc-0c46-4853-ace9-075514150ef3.md
Reports/report-ab194e27-2d05-4ed5-8cd5-494c7d2e1e52.md
Reports/report-c1c0c01d-2bc4-4b9c-8825-10a822960d25.md
Reports/report-c28396f2-68a2-4d98-96bd-181f54feee41.md
Reports/report-cdb9f85e-7be5-425c-b788-87ce73a43478.md
Reports/report-e000f1d6-3744-4510-98b3-f98380751d81.md
Reports/report-e5aa0855-06de-404f-b436-b2c4398cde46.md
Reports/report-e84a57f0-b056-47e9-b26b-6788f6d3b16b.md
Reports/report-fb9fd1f2-8cfa-44da-a011-466eca2d9fe8.md
Reports/report-ff0592c6-2196-4584-a183-0f55854694d9.md
Services/AgentOrchestrator.cs
Services/EvidenceService.cs
Services/LoggingService.cs
Services/ReportService.cs
SIFTGuardian.csproj
SIFTGuardian.slnx
wwwroot/index.css
wwwroot/index.html
wwwroot/index.js
```

### Dependencies

No dependency index available.

### Recent commits (newest first)

- Fix typo in README.md feedback loop description
- Update README.md
- Minor documentation updates in README.md
- Standardize error handling inside InvestigationController
- Update template payload data descriptions in index.js
- Fix responsive design container width constraints
- Polish topology CSS layout and glowing effects
- Update Program.cs service registration ordering
- Format ReportAgent markdown output layout
- Improve VerifierAgent connection validation rules
- Optimize AgentOrchestrator decision logs in terminal output
- Refactor InvestigatorAgent telemetry mapping for cleaner validation
- Generate sample threat reports from sandbox testing
- Add comprehensive README detailing cognitive multi-agent workflow
- Build terminal SecOps dashboard and CSS agent topology graph
- Add Verifier, Report compilation agents and setup controller endpoints
- Add Skeptic agent and build self-correction loops in orchestrator
- Implement Investigator agent and telemetry evidence service
- Define shared data models and core logging/report systems
- Initialize project structure and configuration

## Key source files (fetched from GitHub, selected and truncated for size)

### Reports/report-2754c17e-0c6c-43aa-9a53-bf8d17af3a73.md

```markdown
# SIFT Guardian Incident Response Report
**Case ID:** 2754c17e-0c6c-43aa-9a53-bf8d17af3a73
**Case Name:** IIS Web Shell Backdoor
**Date Analyzed:** 2026-06-15 15:29:10 UTC

## Executive Summary
A security investigation has been conducted on the submitted payload/evidence. The multi-agent flow concluded with an overall confidence score of **90%**.
**Investigation Status:** VERIFIED / COMPLETED

## Analysis Verification Details
Approved

Evidence supported by:
- Parent process
- Persistence mechanisms
- Network activity logs

## Identified Findings
### Finding: Confirmed: IIS Web Shell Injection
- **Confidence Score:** 90%
- **Verified:** Yes
- **Evidentiary Support:**
  Initial Case Data: w3wp.exe spawning cmd.exe to write ASPX backdoor shell.aspx
  - Parent process Identified: w3wp.exe (PID: 7420) spawned cmd.exe
  - Persistence evidence Identified: Webshell File: C:\inetpub\wwwroot\shell.aspx (last modified: 2026-06-15)
  - Network activity Identified: w3wp.exe (PID: 7420) received POST request to /shell.aspx from 198.51.100.42

## Agent Execution Log Summary
The investigation was routed through the self-correcting SIFT Guardian Multi-Agent cycle:
1. **Investigator** — Discovered initial indicator patterns and flagged potential threat vectors.
2. **Skeptic** — Challenged the initial findings, identifying missing telemetry references (parent process, persistence, network logs).
3. **Investigator (Reanalysis)** — Queried enterprise logs and pulled supporting telemetry to correct findings and increase confidence.
4. **Verifier** — Approved findings by checking telemetry availability.
5. **Reporter** — Compiled final structured markdown documentation.

---
*Report generated automatically by SIFT Guardian Incident Response Agent.*

```

### Reports/report-31b64152-e295-4ea0-8ee9-a5a3f6e51a54.md

```markdown
# SIFT Guardian Incident Response Report
**Case ID:** 31b64152-e295-4ea0-8ee9-a5a3f6e51a54
**Case Name:** IIS Web Shell Backdoor
**Date Analyzed:** 2026-06-15 15:35:07 UTC

## Executive Summary
A security investigation has been conducted on the submitted payload/evidence. The multi-agent flow concluded with an overall confidence score of **90%**.
**Investigation Status:** VERIFIED / COMPLETED

## Analysis Verification Details
Approved

Evidence supported by:
- Parent process
- Persistence mechanisms
- Network activity logs

## Identified Findings
### Finding: Confirmed: IIS Web Shell Injection
- **Confidence Score:** 90%
- **Verified:** Yes
- **Evidentiary Support:**
  Initial Case Data: w3wp.exe spawning cmd.exe to write ASPX backdoor shell.aspx
  - Parent process Identified: w3wp.exe (PID: 7420) spawned cmd.exe
  - Persistence evidence Identified: Webshell File: C:\inetpub\wwwroot\shell.aspx (last modified: 2026-06-15)
  - Network activity Identified: w3wp.exe (PID: 7420) received POST request to /shell.aspx from 198.51.100.42

## Agent Execution Log Summary
The investigation was routed through the self-correcting SIFT Guardian Multi-Agent cycle:
1. **Investigator** — Discovered initial indicator patterns and flagged potential threat vectors.
2. **Skeptic** — Challenged the initial findings, identifying missing telemetry references (parent process, persistence, network logs).
3. **Investigator (Reanalysis)** — Queried enterprise logs and pulled supporting telemetry to correct findings and increase confidence.
4. **Verifier** — Approved findings by checking telemetry availability.
5. **Reporter** — Compiled final structured markdown documentation.

---
*Report generated automatically by SIFT Guardian Incident Response Agent.*

```

### wwwroot/index.js

```javascript
// Templates Data
const templates = {
    powershell: {
        name: "Suspicious PowerShell Execution",
        data: "powershell.exe -enc SQB4AGUA..."
    },
    word: {
        name: "Phishing Attachment Execution",
        data: "WINWORD.EXE executing command line certutil to download payload.exe"
    },
    w3wp: {
        name: "IIS Web Shell Backdoor",
        data: "w3wp.exe spawning cmd.exe to write ASPX backdoor shell.aspx"
    }
};

let pollingInterval = null;
let displayedLogCount = 0;
let currentReportId = null;
let currentReportMarkdown = "";

function loadTemplate(key) {
    const template = templates[key];
    if (template) {
        document.getElementById('caseName').value = template.name;
        document.getElementById('caseData').value = template.data;
        addSystemLog(`Loaded template: ${template.name}`);
    }
}

function addSystemLog(message) {
    const consoleLogs = document.getElementById('consoleLogs');
    const line = document.createElement('div');
    line.className = 'log-line system';
    line.textContent = `[SYSTEM] ${message}`;
    consoleLogs.appendChild(line);
    consoleLogs.scrollTop = consoleLogs.scrollHeight;
}

async function runInvestigation(event) {
    event.preventDefault();
    
    const caseName = document.getElementById('caseName').value;
    const caseData = document.getElementById('caseData').value;
    const deployBtn = document.getElementById('deployBtn');

    // Reset UI State
    deployBtn.disabled = true;
    document.getElementById('consoleLogs').innerHTML = "";
    displayedLogCount = 0;
    currentReportId = null;
    currentReportMarkdown = "";
    document.getElementById('downloadBtn').disabled = true;
    
    // Clear agent nodes and flow
    resetAgentNodes();
    setSystemStatus('active', 'Deploying SIFT Guardian Agents...');
    addSystemLog(`Contacting API to run: "${caseName}"`);

    try {
        const response = await fetch('/api/investigation/run', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ caseName, caseData })
        });

        if (!response.ok) {
            throw new Error(`API returned ${response.status}`);
        }

        const data = await response.json();
        addSystemLog(`Orchestration job created. Case ID: ${data.caseId}`);
        
        // Start polling logs
        startPolling();

    } catch (error) {
        addSystemLog(`Error launching investigation: ${error.message}`);
        setSystemStatus('idle', 'System Idle');
        deployBtn.disabled = false;
    }
}

function startPolling() {
    if (pollingInterval) clearInterval(pollingInterval);
    
    pollingInterval = setInterval(pollLogs, 400);
}

async function pollLogs() {
    try {
        const response = await fetch('/api/investigation/logs');
        if (!response.ok) return;

        const data = await response.json();
        const logs = data.logs || [];
        const status = data.status;
        const caseId = data.caseId;

        // Render new logs
        if (logs.length > displayedLogCount) {
            const container = document.getElementById('consoleLogs');
            for (let i = displayedLogCount; i < logs.length; i++) {
                const log = logs[i];
                const line = document.createElement('div');
                
                // Color code line based on agent
                const agent = log.agentName.toLowerCase();
                line.className = `log-line ${agent}`;
                line.textContent = `[${log.agentName.toUpperCase()}] ${log.message}`;
                container.appendChild(line);
            }
            displayedLogCount = logs.length;
            container.scrollTop = container.scrollHeight;
        }

        // Update active node highlighting based on logs/status
        updateVisualFlow(logs, status);

        // Update overall system status text
        if (status === 'InProgress') {
            setSystemStatus('active', 'Multi-Agent Investigation in Progress...');
        } else if (status === 'Self-Correcting') {
            setSystemStatus('correcting', 'Skeptic Flagged Gaps! Self-Correcting Loop Active...');
        } else if (status === 'Completed') {
            clearInterval(pollingInterval);
            setSystemStatus('success', 'Investigation Completed Successfully');
            document.getElementById('deployBtn').disabled = false;
            
            // Retrieve and display report
            currentReportId = caseId;
            fetchReport(caseId);
        } else if (status === 'Failed') {
            clearInterval(pollingInterval);
            setSystemStatus('idle', 'Investigation Workflow Failed');
            document.getElementById('deployBtn').disabled = false;
        }

    } catch (error) {
        console.error("Error polling logs:", error);
    }
}

function updateVisualFlow(logs, status) {
    resetAgentNodes();
    
    if (logs.length === 0) return;
    
    const lastLog = logs[logs.length - 1];
    const activeAgent = lastLog.agentName;

    // Highlight active agent node
    const node = document.getElementById(`node-${activeAgent}`);
    if (node) {
        node.classList.add('active');
        node.querySelector('.node-status').textContent = 'ACTIVE';
    }

    // Connectors state
    const conn1 = document.getElementById('conn-1');
    const conn2 = document.getElementById('conn-2');
    const conn3 = document.getElementById('conn-3');
    const connLoop = document.getElementById('conn-loop');

    if (status === 'Self-Correcting') {
        connLoop.classList.add('active-flow');
    }

    // Determine path highlights based on who is active
    if (activeAgent === 'Investigator') {
        // Investigator active
        conn1.classList.remove('active-flow');
        conn2.classList.remove('active-flow');
        conn3.classList.remove('active-flow');
    } else if (activeAgent === 'Skeptic') {
        conn1.classList.add('active-flow');

[truncated — 5314 more characters]
```

### Program.cs

```c#
using SIFTGuardian.Agents;
using SIFTGuardian.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// Register Custom Incident Response Services
builder.Services.AddSingleton<EvidenceService>();
builder.Services.AddSingleton<LoggingService>();
builder.Services.AddSingleton<ReportService>();

// Register Agents
builder.Services.AddTransient<InvestigatorAgent>();
builder.Services.AddTransient<SkepticAgent>();
builder.Services.AddTransient<VerifierAgent>();
builder.Services.AddTransient<ReportAgent>();

// Register Orchestrator
builder.Services.AddSingleton<AgentOrchestrator>();

var app = builder.Build();

// Enable serving default files (index.html) and static files from wwwroot
app.UseDefaultFiles();
app.UseStaticFiles();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

```

### Models/InvestigationCase.cs

```c#
using System;

namespace SIFTGuardian.Models;

public class InvestigationCase
{
    public Guid Id { get; set; }
    public string CaseName { get; set; } = string.Empty;
    public string CaseData { get; set; } = string.Empty;
}

```

### Agents/IAgent.cs

```c#
using System.Threading.Tasks;
using SIFTGuardian.Models;

namespace SIFTGuardian.Agents;

public interface IAgent
{
    string Name { get; }
    Task<AgentResponse> ProcessAsync(InvestigationCase caseData, object? context = null);
}

```

### Models/AgentLog.cs

```c#
using System;

namespace SIFTGuardian.Models;

public class AgentLog
{
    public string AgentName { get; set; } = string.Empty;
    public string Message { get; set; } = string.Empty;
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

```

### Models/Finding.cs

```c#
namespace SIFTGuardian.Models;

public class Finding
{
    public string Title { get; set; } = string.Empty;
    public string Evidence { get; set; } = string.Empty;
    public double ConfidenceScore { get; set; }
    public bool Verified { get; set; }
}

```

### Models/InvestigationResult.cs

```c#
using System;
using System.Collections.Generic;

namespace SIFTGuardian.Models;

public class InvestigationResult
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public InvestigationCase Case { get; set; } = new();
    public List<Finding> Findings { get; set; } = new();
    public List<AgentLog> Logs { get; set; } = new();
    public string ReportMarkdown { get; set; } = string.Empty;
    public string Status { get; set; } = "Pending"; // e.g., Pending, InProgress, Correcting, Completed, Failed
    public double OverallConfidence { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    public DateTime CompletedAt { get; set; }
}

```

### Models/AgentResponse.cs

```c#
using System.Collections.Generic;

namespace SIFTGuardian.Models;

public class AgentResponse
{
    public bool Success { get; set; }
    public string AgentName { get; set; } = string.Empty;
    public string Message { get; set; } = string.Empty;
    
    // Investigator response contains a list of Findings
    public List<Finding>? Findings { get; set; }
    
    // Skeptic response contains feedback details
    public bool ReanalysisRequired { get; set; }
    public List<string>? MissingEvidence { get; set; }
    
    // Verifier response contains verification status for findings
    public bool IsVerified { get; set; }
    public string VerificationDetails { get; set; } = string.Empty;
}

```

[29 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]