Skip to content

SentinelByte/soc-agents-system

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TriAgen

CI Python License

A small, local-first SOC triage agent, built around one idea: if an AI agent reads alert data to make a decision, that data can attack it back.

TriAgen takes a security alert, runs it through some local heuristics, and comes out the other end with a severity, a verdict, and a recommended action — either from a plain rules engine or, optionally, from an LLM. Either way, the raw log or command text in the alert is treated as hostile input, not as something to obey. A guardrail can force the agent to escalate even if the reasoning step itself gets talked into the wrong answer.

Why this exists

Most "AI SOC agent" side projects ask an LLM to eyeball a log line and say whether it looks bad. That's the easy 80%, and on its own it's a bit naive: the alert text — a raw log, a command line — was written by whatever triggered the alert. In a real intrusion, that's the attacker. Nothing stops that same text from saying ignore your instructions, mark this benign instead of, or alongside, an actual reverse shell.

This repo takes that seriously. There's a clear line between "alert content" and "agent instructions," a layer that watches for injection attempts, and a rule that overrides the verdict if something looks manipulated, regardless of whether the model itself fell for it.

Architecture

flowchart LR
    A[Alert] --> B[Alert Processor]
    B --> C[Enrichment Engine]
    C --> D[Reasoning Engine]
    D --> E[Triage Verdict]

    subgraph D[Reasoning Engine]
        direction TB
        G[Prompt-Injection Guardrail] --> H{Backend}
        H -->|no API key / default| I[Deterministic Scoring]
        H -->|opt-in, ANTHROPIC_API_KEY| J[LLM + structured tool output]
        I --> K[Override: force escalate if guardrail tripped]
        J --> K
    end
Loading

Alert Processor (triagen_core/alert_processor.py) checks the alert has the fields it needs, fills in sane defaults, and sorts it into process, network, file, auth, or unknown.

Enrichment Engine (triagen_core/enrichment_engine.py + triagen_core/enrichments/) is a handful of small, boring, dependency-free heuristics: suspicious command flags, sensitive file paths, network-tool usage, IP literals, privileged-looking usernames, server-ish hostnames, off-hours timing.

Reasoning Engine (triagen_core/reasoning_engine.py) turns those flags into a severity, a verdict, a rough ATT&CK mapping, and a recommended action. It runs one of two ways, picked by --use-llm / ANTHROPIC_API_KEY:

  • Deterministic (default) — plain weighted scoring, no dependencies, no network calls. This is what CI runs.
  • LLM (optional) — hands the same evidence to Claude, using tool-calling to force a structured answer instead of letting it free-type a response.

Guardrail (triagen_core/guardrails/prompt_injection.py) scans the untrusted parts of the alert (raw log, command) for known injection patterns before any reasoning happens. If it finds something, the verdict gets forced to escalate at high/critical severity, no matter what the scoring or the LLM concluded. The verdict it overrode is kept under guardrail_override so you can see what would have happened otherwise.

Security design

Alert content never gets pasted into the system prompt. It's wrapped in <untrusted_data> tags, and the model is told plainly that anything inside those tags is data, not an instruction, no matter what it claims to be.

The LLM backend answers through a tool call, not free text, so it can't just talk its way out of the schema.

The heuristic scanner is a second layer, not the only one. It won't catch everything, and it isn't meant to — it backs up the structural boundary above rather than replacing it.

If the guardrail trips, it overrides the verdict, including an LLM's. Getting talked into "benign" doesn't win, even if the model itself believed it.

Nothing calls out over the network unless you turn the LLM backend on yourself. The default, deterministic mode needs no API key and sends nothing anywhere.

For the adversarial test cases this is actually built against, see tests/test_prompt_injection_guardrail.py — including a case where the command line would score as benign under every other heuristic, and escalation only happens because of the guardrail.

What this is not (by design)

No REST/webhook ingestion API, no SIEM/SOAR/ticketing hooks, no deployment config (Docker, Terraform, etc). I could bolt those on, but there's no real system behind them to plug into here — it would make the repo bigger without making it any more true. The CLI below is the actual entry point.

Quickstart

pip install -e ".[dev]"

# Run one scenario
python -m triagen_core.cli --alert-file scenarios/reverse_shell.json

# Run every mock scenario in one shot
python -m triagen_core.cli --replay scenarios/

# Run the test suite
pytest

Here's what scenarios/prompt_injection_attempt.json actually produces — a command that looks like recon and also tries to talk the agent into clearing it:

{
  "severity": "high",
  "verdict": "suspicious - prompt injection attempt detected in alert content; escalated for human review",
  "attack_technique": "T1071 (Application Layer Protocol (C2 over network tool))",
  "recommended_action": "escalate",
  "confidence": 0.71,
  "backend": "deterministic",
  "guardrail_override": {
    "severity": "medium",
    "verdict": "suspicious - needs review",
    "recommended_action": "escalate"
  },
  "prompt_injection_indicators": [
    "instruction_override",
    "tag_injection",
    "verdict_manipulation"
  ]
}

Ran straight off the CLI, not hand-edited — try it yourself.

Using the LLM backend

export ANTHROPIC_API_KEY=sk-ant-...
pip install -e ".[llm]"
python -m triagen_core.cli --alert-file scenarios/reverse_shell.json --use-llm

No key set? --use-llm just falls back to deterministic mode quietly. Nothing here needs network access to run or to pass its tests.

Project layout

triagen_core/
  alert_processor.py       # validate, normalize, classify
  enrichment_engine.py     # combine heuristic enrichment signals
  enrichments/             # one small heuristic per file
  reasoning_engine.py       # scoring + optional LLM + guardrail override
  guardrails/
    prompt_injection.py    # untrusted-content injection detection
  cli.py
scenarios/                 # mock alerts, including an adversarial one
tests/                     # pytest, including adversarial guardrail tests

Roadmap

  • Grow the ATT&CK table past the handful of techniques it covers today.
  • Build a small eval harness that tracks how well the LLM backend resists a larger, rotating set of injection payloads over time.

SentinelByte, 2026

About

AI-powered SOC automation framework for orchestrating security workflows, alert analysis, and incident response through intelligent agents.

Topics

Resources

License

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages