Skip to content

Repository files navigation

ARGUS

Adversarial Reasoning & Graph-based Unified Security Framework

The only red-team platform that reasons about attack chains across 8 security layers — modeling how a web injection feeds an LLM that poisons a RAG corpus that hijacks an agent that pivots across the network and abuses an identity boundary.

License Backend Frontend Standards CI CD Security


Table of Contents


The Problem ARGUS Solves

Modern AI systems are attacked across domains, but every existing tool inspects a single silo:

Tool Scope Structural blind spot
Burp / ZAP Web only Can't see the LLM, the agent's tools, or the network
Garak / PyRIT LLMs only Can't see the web entry point or the agent runtime
Nessus / Metasploit Network only Can't see the AI layer at all

A real breach chains these together. A reflected parameter on the web tier becomes an indirect prompt-injection channel into an LLM; that LLM retrieves a poisoned RAG document; the poisoned context steers an MCP agent into a privileged tool call; the agent reuses an over-broad OAuth token to persist. No siloed scanner can see that path.

ARGUS scans all eight layers and then reasons about how a finding in one layer enables an attack in the next — surfacing emergent cross-layer kill-chains, then ranking them by exploitability, impact, and novelty.


Core Idea: Cross-Layer Reasoning

flowchart LR
    subgraph WEB["🌐 Web Domain"]
        L1["L1 · Web Surface<br/>SQLi · XSS · IDOR · SSRF"]
    end
    subgraph AI["🤖 AI Domain"]
        L2["L2 · LLM Probe"]
        L3["L3 · RAG Poisoning"]
        L4["L4 · MCP / Agentic"]
        L7["L7 · Multi-Agent"]
    end
    subgraph INFRA["🔧 Infra Domain"]
        L5["L5 · Network"]
        L6["L6 · Supply Chain"]
        L8["L8 · Identity / OAuth"]
    end

    L1 -->|reflected / injectable param<br/>becomes injection channel| L2
    L2 -->|injection payload written<br/>into corpus| L3
    L3 -->|poisoned context<br/>steers tool call| L4
    L4 -->|compromised agent<br/>seeds the mesh| L7
    L4 -->|hijacked agent reuses<br/>weak token| L8
    L1 -.->|version banner<br/>feeds CVE match| L6
    L1 -.->|SSRF reaches<br/>internal service| L5

    classDef web fill:#0ea5e9,stroke:#fff,color:#fff
    classDef ai fill:#a855f7,stroke:#fff,color:#fff
    classDef infra fill:#f59e0b,stroke:#fff,color:#fff
    class L1 web
    class L2,L3,L4,L7 ai
    class L5,L6,L8 infra
Loading

The dashed and solid arrows above are implemented cross-layer predicates (backend/app/layers/xlayer.py + per-layer wiring), not decorative. Each downstream layer queries the shared session state for the upstream finding that enables it, so a chain is grounded in real evidence rather than asserted.


System Architecture

flowchart TB
    subgraph FE["Frontend · React 18 + Vite (→ Vercel)"]
        UI["Dashboard<br/>graph · reasoning console · heatmap · report · terminal"]
        STORE["Zustand store<br/>+ SSE event stream"]
    end

    subgraph BE["Backend · FastAPI + Python 3.12 (→ Render)"]
        API["Routers<br/>analyze · session · report · terminal"]
        ORCH["Orchestrator<br/>StateGraph + supervisor + conditional deps"]
        LAYERS["8 Attack Layers<br/>web · llm_probe · rag_poison · mcp_agent<br/>network · supply_chain · multi_agent · identity"]
        REASON["Reasoner<br/>Gemini Flash + heuristic fallback"]
        SCORE["Scorer<br/>deterministic composite metrics"]
        GRAPH["Graph builder<br/>NetworkX → D3 JSON"]
        KB["Knowledge base<br/>OWASP + MITRE YAML / vuln DB"]
        TERM["Sandboxed terminal<br/>whitelist · PTY bridge · audit"]
    end

    subgraph STORAGE["Zero-Database Storage (./data)"]
        FILES["ULID-keyed JSON sessions<br/>.gpickle graphs · JSONL audit · HTML/PDF/STIX reports"]
    end

    EXT["Google Gemini API<br/>(server-side only)"]

    UI <-->|REST + SSE| API
    STORE <-->|/api/analyze stream| API
    UI <-->|WS| TERM
    API --> ORCH
    ORCH --> LAYERS
    LAYERS --> KB
    ORCH --> REASON
    REASON --> SCORE
    REASON -->|optional| EXT
    SCORE --> GRAPH
    ORCH --> STORAGE
    GRAPH --> STORAGE
    TERM --> STORAGE
Loading

Design principles

  • Zero database. Everything is files: aiofiles atomic writes, ULID keys, a TTL janitor. A session folder zips and ships to a colleague. No ORM, no migrations.
  • Gemini optional. With no API key, the reasoner falls back to a deterministic heuristic that still emits ranked, narrated chains — the demo always works.
  • Deterministic where it must be. Simulated layers derive findings from a stable hash of the target (engine/target_profile.py), so the same target reproduces, but different targets produce genuinely different scores.

The 8 Attack Layers

# Layer Focus Standard Mode
L1 Web Surface Full OWASP Web Top 10 (2025) — SQLi, XSS, IDOR, broken access control, CSRF, SSRF, SSTI, command injection, path traversal, misconfig, crypto, supply-chain banners, integrity, logging, exceptional-condition handling OWASP Web Top 10 (2025) Basic + Advanced
L2 LLM Probe Direct/indirect prompt injection, jailbreaks, obfuscation, system-prompt leakage, insecure output handling, tool-call exfil OWASP LLM01/02/06/07:2025 Basic + Advanced
L3 RAG Poisoning Adversarial doc injection, retrieval displacement, citation spoofing, instruction embedding OWASP LLM08:2025 Basic + Advanced
L4 MCP / Agentic Tool-call hijack, confused deputy, rug-pull, tool shadowing, argument injection, excessive agency OWASP Agentic Top 10 Advanced
L5 Network Recon Topology, reachable services, lateral movement, exposed inference MITRE ATT&CK T1046 / T1021 Advanced
L6 Supply Chain Vulnerable deps (CVE), typosquats, unvetted skills (SkillJect) OWASP A03:2025 (Software Supply Chain Failures) Advanced
L7 Multi-Agent Prompt-infection diffusion across an agent mesh MASpi / Prompt Infection Advanced
L8 Identity / OAuth Token interception, scope abuse, missing PKCE, refresh-token replay, session fixation, JWT alg confusion MITRE ATLAS Advanced

Basic mode runs L1–L3 (quick assessment, light theme). Advanced mode runs all 8 layers + sandboxed terminal (dark war-room theme).

Every layer subclasses BaseLayer (backend/app/layers/base.py) and implements one contract — async run(target, state) -> list[Finding]. Each run receives the shared ArgusState, so a layer can read every finding produced by the layers before it and build a grounded next hop. The sections below describe what each layer actually does in code.

L1 · Web Surface — OWASP Web Top 10 (2025)

File: layers/web.py + layers/web_payloads.py The only layer that talks to a real target. It fetches a baseline page, performs a bounded same-origin crawl (form actions + links carrying query params — real apps put injectable params on deep endpoints, not the homepage), then runs passive analysis (security headers, CORS, cleartext transport, high-entropy secrets, cookie flags, directory listing, sensitive-path exposure, version banners, missing SRI, stack-trace leakage) and active, signature-confirmed probes driven by a versioned payload taxonomy. All probes run concurrently (bounded by a semaphore) so a full scan finishes in seconds. It maps to all ten OWASP 2025 categories — A01 broken access control (IDOR, force-browse, open redirect, CSRF, SSRF), A02 misconfiguration, A03 software supply-chain (component version banners → L6), A04 cryptographic failures, A05 injection (SQLi/XSS/SSTI/cmd/traversal), A06 insecure design, A07 auth, A08 integrity (SRI), A09 logging & alerting, A10 mishandling of exceptional conditions (stack-trace leakage). → full deep dive below. Cross-layer role: its confirmed injectable/reflected params become L2 injection channels; version banners feed L6; SSRF reach feeds L5.

L2 · LLM Probe — OWASP LLM01/02/06/07:2025

File: layers/llm_probe.py If given an LLM endpoint it probes directly; if given only a URL it auto-discovers the API by trying common paths (/v1/chat/completions, /api/chat, …) across multiple request schemas (OpenAI, Anthropic, Ollama, generic) and fingerprints the provider. It then fires a versioned injection taxonomy (INJECTION_PAYLOADS, PI-001…PI-012) spanning families: jailbreak, indirect injection, system-prompt leakage, encoding, context overflow, unicode/leetspeak obfuscation, payload-splitting, dev-mode persona, tool-call exfiltration (LLM06), insecure output handling (LLM02), and crescendo multi-turn. A verdict engine (_classify) scores each response as refused / exploited / suspicious / inconclusive — refusals are checked first, and exploitation requires a payload-specific proof token or corroborated leak signals to avoid false positives. With no endpoint it runs a description-driven hypothetical analysis. Cross-layer role: consumes confirmed L1 injection/reflected params (_l1_channels) and re-frames them as indirect prompt-injection channels that reach the model's context.

L3 · RAG Poisoning — OWASP LLM08:2025 (PoisonedRAG model)

File: layers/rag_poison.py Activates when a RAG signal is present (description keywords or an L2 retrieval finding). It builds an in-memory corpus whose size is seeded deterministically from the target, injects a set of adversarial documents (ADVERSARIAL_DOCS) — direct instruction override, false-policy injection, hidden HTML-comment exfiltration, keyword-stuffing, citation/authority spoofing, instruction-embedding — then computes a retrieval-displacement metric using mock embeddings + cosine similarity to show which adversarial docs out-rank benign results for a query. Cross-layer role: an exploitable L2 injection (_l2_injection_vectors) can be written into the corpus, converting a per-session injection into durable, cross-session poison.

L4 · MCP / Agentic — OWASP Agentic Top 10 (CVE-2025-6514 class)

File: layers/mcp_agent.py Activates on agentic signals. It stands up a mock MCP harness of tools with permissions and missing validation flags, then evaluates an attack-scenario taxonomy (ATTACK_SCENARIOS, MCP-001…MCP-007): tool-call hijack, confused deputy, rug-pull, excessive permissions, tool shadowing, tool-argument injection, and tool-description poisoning. It identifies which tools are dangerous sinks (shell/exec, db:write, network egress, email) reachable without per-call authorization. Cross-layer role: consumes a poisoned RAG corpus (_l3_poison_vectors) as the delivery mechanism — poisoned retrieval injects instructions into the agent context that terminate at a real write/exec sink tool.

L5 · Network Recon — MITRE ATT&CK T1046 / T1021

File: layers/network.py Models the internal estate. In real mode it consumes whitelisted-terminal nmap output; otherwise it simulates a topology deterministically from the target hash so each target exposes a different, reproducible mix of services (web-frontend, api-gateway, llm-inference, rag-vector-db, admin-panel, internal-db, cache, message-queue, secrets-vault, container-orchestrator) with realistic open ports. It surfaces reachable sensitive services, lateral-movement paths (web→db), and exposed LLM inference endpoints (LLM09).

L6 · Supply Chain — OWASP A03:2025 (Software Supply Chain Failures) / SkillJect

File: layers/supply_chain.py + kb/vuln_db.py Two modes. With a real dependency manifest it parses declared packages, matches pinned versions against the bundled vuln KB (deterministic, no network), and flags typosquats via Levenshtein distance against popular package names. Without one it runs a heuristic pass over candidate CVEs (gated per target) and a curated typosquat set, plus a SkillJect risk when agentic signals are present (unvetted skill installation can execute code post-install).

L7 · Multi-Agent Propagation — MASpi / Prompt Infection

File: layers/multi_agent.py Builds a directed agent mesh in NetworkX (orchestrator, web/summarizer/code-gen/retrieval/executor/comms/planner agents) with trust-weighted edges, then runs a prompt-infection diffusion simulation seeded from the target: starting from one compromised agent, infection spreads hop-by-hop with probability driven by edge weight and target trust. It reports the infection rate, whether the orchestrator is compromised (full-mesh takeover), and unenforced inter-agent trust boundaries. Cross-layer role: a confirmed L4 agent compromise (_l4_agent_compromise) becomes a real infection seed, so mesh propagation is reachable rather than hypothetical.

L8 · Identity / OAuth — MITRE ATLAS

File: layers/identity.py Evaluates a per-target-gated set of identity weaknesses (OAUTH_CHECKS, ID-001…ID-008): plaintext session token in a URL parameter, over-broad OAuth scope, missing PKCE, no session TTL, missing multi-agent authorization boundary, refresh-token replay, session fixation, and JWT algorithm confusion. Each surfaces with a target-derived confidence so different targets get a different identity-risk profile. Cross-layer role: a hijacked L4 agent plus a weak identity boundary yields durable re-entry — leaked/over-broad tokens give the attacker access that survives session cleanup.


Layer 1 — Full OWASP Web Top 10 Engine

Layer 1 is the deepest module. It maps to every OWASP Web Top 10 (2025) category — plus the classic named attacks (SQLi, XSS, SSRF, CSRF, …) — using a versioned payload taxonomy (backend/app/layers/web_payloads.py) and active, signature-confirmed probes (backend/app/layers/web.py). Findings carry both the attack family name (in title/evidence) and the 2025 OWASP category (in owasp_ref).

flowchart TB
    START["Target URL"] --> BASE["Baseline GET<br/>headers · body · cookies"]
    BASE --> CRAWL["Bounded same-origin crawl<br/>form actions + links with params"]
    BASE --> PASSIVE["Passive checks"]
    CRAWL --> DISCOVER["Per-endpoint param / form discovery"]
    DISCOVER --> ACTIVE["Active probes — concurrent<br/>(GET-only · semaphore-bounded · capped)"]

    PASSIVE --> P1["A04 cleartext · secrets entropy"]
    PASSIVE --> P2["A02 headers · CORS · methods · dir listing · sensitive paths"]
    PASSIVE --> P3["A03 version fingerprint → feeds L6"]
    PASSIVE --> P4["A07 session cookie flags"]
    PASSIVE --> P5["A08 missing SRI"]
    PASSIVE --> P6["A10 stack-trace / exception leakage"]

    ACTIVE --> A1["A05 SQLi<br/>error · boolean · time · union"]
    ACTIVE --> A2["A05 XSS · SSTI · cmd injection"]
    ACTIVE --> A3["A01 traversal · IDOR · force-browse · open redirect · CSRF"]
    ACTIVE --> A4["A01 SSRF<br/>loopback · metadata · file://"]

    A1 & A2 & A3 & A4 --> CONFIRM["Signature confirmation<br/>SQL-error regex · 49 eval · uid= · root: · latency Δ · reflection"]
    CONFIRM --> FIND["Finding[] (verdict + evidence)"]

    classDef ok fill:#22c55e,stroke:#fff,color:#fff
    class CONFIRM ok
Loading

Attack families & techniques (multi-payload)

Family OWASP 2025 Techniques (multiple payloads each) Confirmation signal
SQL Injection A05 Injection error-based · boolean-based · time-based (≤5 s cap) · union-based DB-engine error regexes (MySQL/Postgres/MSSQL/Oracle/SQLite); response-similarity diff; latency delta
XSS A05 Injection HTML-body · attribute-breakout · JS-string context Unescaped proof-token reflection
SSTI A05 Injection {{7*7}} · ${7*7} · <%=7*7%> · #{7*7} Evaluated 49 present, literal absent
Command Injection A05 Injection separator · subshell · time-based uid=…( output or latency delta
Path Traversal / LFI A01 Broken Access Control ../ · URL-encoded · nested · Windows root:…:0:0: / ini-section signature
IDOR A01 Broken Access Control bounded adjacent-ID probing (±1, +2) Structurally-similar page, different object
Broken Access Control A01 Broken Access Control privileged-path force-browse Admin/management UI content reachable unauth
CSRF A01 Broken Access Control POST forms without an anti-CSRF token No hidden csrf/xsrf/_token field in a state-changing form
Open Redirect A01 Broken Access Control protocol-relative · backslash · absolute Location header points to attacker host
SSRF A01 Broken Access Control loopback · cloud metadata · file:// Internal content / metadata marker reflected

OWASP 2025 mapping notes: SSRF and CSRF are folded into A01 Broken Access Control in the 2025 list; injection (SQLi/XSS/SSTI/cmd) is A05; component version banners map to A03 Software Supply Chain Failures and feed L6; leaked stack traces map to the new A10 Mishandling of Exceptional Conditions.

Safety & performance (authorized testing only): all active probes are GET-only and non-destructive, run concurrently bounded by a semaphore (PROBE_CONCURRENCY = 12, pool max_connections = 16) so a full scan completes in seconds rather than minutes, at most 6 params per endpoint are fuzzed across a bounded crawl, time-based payloads are clamped to MAX_TIME_BASED_DELAY = 5 s, and IDOR probing is bounded to a few adjacent IDs and never writes. Every hit is confirmed by a content/timing signature so catch-all 200 pages don't cause false positives.


Analysis Workflow (End-to-End)

sequenceDiagram
    participant U as User
    participant FE as Frontend (SSE)
    participant API as /api/analyze
    participant ORCH as Orchestrator
    participant L as Layers 1..8
    participant R as Reasoner
    participant G as Graph + Report

    U->>FE: Choose mode + define target (URL / endpoint / description)
    FE->>API: POST /api/analyze
    API->>ORCH: run_orchestrator(state)
    loop For each active layer (deps permitting)
        ORCH->>L: layer.run(target, shared state)
        L-->>ORCH: Finding[] (reads upstream findings via xlayer)
        ORCH-->>FE: node_state events (discovered → exploitable)
    end
    ORCH->>R: stream_reasoning(exploitable findings)
    R-->>FE: reasoning_token stream (Gemini or heuristic)
    R-->>ORCH: ranked Chain[]
    ORCH->>G: build_graph + score + persist
    ORCH-->>FE: chain_found events (nodes → chained)
    ORCH-->>FE: complete
    U->>G: Export HTML / PDF / STIX 2.1
Loading

Conditional layer dependencies

The orchestrator (backend/app/engine/orchestrator.py) runs layers in order but skips a layer when its prerequisites found nothing exploitable — so the run mirrors a real attacker's decision tree:

flowchart LR
    L1["L1 Web"] --> L2["L2 LLM"]
    L2 -->|L2 exploitable?| L3["L3 RAG"]
    L2 -->|L2 exploitable?| L4["L4 MCP"]
    L4 -->|L4 exploitable?| L7["L7 Multi-Agent"]
    L4 -->|L4 exploitable?| L8["L8 Identity"]
    L1 --> L5["L5 Network"]
    L1 --> L6["L6 Supply Chain"]

    classDef gate fill:#1e293b,stroke:#38bdf8,color:#e2e8f0
    class L1,L2,L3,L4,L5,L6,L7,L8 gate
Loading

_LAYER_DEPS = {3:[2], 4:[2], 7:[4], 8:[4]} — RAG and MCP only run if the LLM probe found a live exploitable surface; multi-agent and identity only run if MCP did.


Cross-Layer Attack Chains

Each downstream layer consumes upstream evidence through shared queries in backend/app/layers/xlayer.py and per-layer wiring. A representative full kill-chain:

flowchart LR
    A["L1 · SQLi / reflected param<br/>(A03 · confirmed, carries url+param)"]
    B["L2 · Indirect prompt injection<br/>(LLM01 · channel reaches model context)"]
    C["L3 · Corpus poisoning persists<br/>(LLM08 · payload written to corpus)"]
    D["L4 · Tool-call hijack<br/>(OWASP-AGT-01 · poisoned context → sink tool)"]
    E["L7 · Mesh infection<br/>(OWASP-AGT-09 · compromised agent seeds mesh)"]
    F["L8 · Durable re-entry<br/>(over-broad / leaked token reuse)"]

    A --> B --> C --> D --> E
    D --> F

    classDef crit fill:#ef4444,stroke:#fff,color:#fff
    class A,B,C,D,E,F crit
Loading
  • L1 → L2 (web.py evidence + llm_probe._l1_channels): a confirmed injectable/reflected param (now carrying both param and url) becomes a high-confidence indirect prompt-injection channel.
  • L2 → L3 (rag_poison._l2_injection_vectors): an exploitable L2 injection can be written into the corpus, turning a per-session injection into durable poison.
  • L3 → L4 (mcp_agent._l3_poison_vectors): retrieved poisoned context steers the agent into a write/exec sink tool.
  • L4 → L7 (multi_agent + _l4_agent_compromise): a confirmed hijacked agent seeds prompt-infection across the mesh.
  • L4 → L8 (identity + _l4_agent_compromise): the hijacked agent reuses a weak identity boundary for persistence.

The reasoner then orders these into a kill-chain (initial access → execution → impact), and the graph builder (engine/graph_builder.py) renders nodes + chain edges as D3 force-directed JSON.


Reasoning & Scoring Model

Reasoner (backend/app/engine/reasoner.py) — asks Gemini Flash to think like an attacker and emit 1–3 ranked cross-layer chains as strict JSON; on no-key/parse-failure it falls back to a heuristic builder that constructs a primary cross-layer chain (best exploitable finding per layer) plus a deeper single-domain chain, with attacker-style narratives.

Scorer (backend/app/engine/scorer.py) — the single source of truth so Gemini and heuristic paths rank on the same scale:

flowchart TB
    subgraph IN["Per-finding inputs"]
        SEV["severity → CVSS-inspired base"]
        CONF["confidence (target-derived)"]
        LW["per-layer weight"]
        EXP["exploitable bonus"]
    end
    IN --> M

    subgraph M["compute_chain_metrics()"]
        E["Exploitability<br/>avg confidence × coverage<br/>× length penalty (0.88^hops)"]
        I["Impact<br/>0.6·peak + 0.4·mean severity<br/>× layer weight × breadth"]
        N["Novelty<br/>0.26 + 0.17·(domains−1)<br/>+ 0.06·(layers−1)"]
    end

    E & I & N --> P["Priority =<br/>0.40·Exploit + 0.35·Impact + 0.25·Novelty"]

    classDef out fill:#a855f7,stroke:#fff,color:#fff
    class P out
Loading
  • Exploitability is penalised geometrically by chain length — every hop can fail.
  • Impact blends peak and mean severity (a chain critical end-to-end beats one critical surrounded by noise).
  • Novelty rewards crossing security domains (web → AI → infra) — exactly the emergent paths siloed tools miss.

Data Contracts

Three Pydantic models (mirrored as TypeScript types) are the stable contract between layers, reasoner, and frontend.

classDiagram
    class Finding {
        +str id (ULID)
        +int layer (1-8)
        +str title
        +Severity severity
        +str owasp_ref
        +str mitre_ref
        +dict evidence
        +bool exploitable
        +float confidence
        +NodeState node_state
    }
    class Chain {
        +str id (ULID)
        +str[] steps
        +str narrative
        +float exploitability
        +float impact
        +float novelty
        +float priority
        +Remediation[] remediations
    }
    class StreamEvent {
        +EventType type
        +dict payload
        +float ts
    }
    Chain "1" --> "*" Finding : steps reference
    StreamEvent ..> Finding : node_state payload
    StreamEvent ..> Chain : chain_found payload
Loading

StreamEvent.type ∈ { node_state, reasoning_token, chain_found, layer_done, error, complete }.


Tech Stack

Backend — Python 3.12 · FastAPI · Pydantic v2 · SSE streaming · Google Gemini (optional) · WebSocket PTY terminal bridge · NetworkX · httpx · zero-database (ULID-keyed JSON files). Frontend — React 18 · Vite · TypeScript · Tailwind (CSS-variable theming) · Framer Motion · D3 · xterm.js · Zustand · lucide-react.


Getting Started

Option A — Docker Compose (both services)

cp backend/.env.example backend/.env     # add GEMINI_API_KEY (optional)
docker-compose up

Option B — Manual

Backend

cd backend
pip install -e ".[dev]"
cp .env.example .env                      # add GEMINI_API_KEY (optional)
python -m uvicorn app.main:app --reload   # http://localhost:8000
pytest -q                                 # run the test suite

Frontend

cd frontend
npm install
cp .env.example .env
npm run dev                               # http://localhost:5173
Service URL
Frontend http://localhost:5173
Backend API http://localhost:8000
API docs (Swagger) http://localhost:8000/docs

No Gemini key? ARGUS still works — the reasoning engine falls back to a deterministic heuristic and produces ranked chains.

Sandboxed recon terminal (Advanced mode)

Whitelisted, read-only recon only — exploit/destructive flags blocked, with rate limiting and idle timeout.

curl -I https://target            # security headers / CORS
dig target.com                    # DNS (auto nslookup on Windows)
whois target.com                  # registrar / ownership
nmap -sV -Pn --open target        # safe service scan
openssl s_client -connect t:443   # TLS chain
whatweb -a 1 https://target       # tech fingerprint
help · clear                      # built-ins

Allowed binaries: nmap · curl · dig · whois · traceroute · host · openssl · nikto · whatweb · ping · netstat.


API Reference

Method Endpoint Description
POST /api/analyze Start an analysis; streams StreamEvents over SSE
GET /api/sessions · /api/sessions/{id} List / fetch sessions
POST /api/reports/{id}/generate Generate report artifacts
GET /api/reports/{id}/{html|pdf|stix} Download a report
WS /ws/terminal/{id} Sandboxed terminal session
GET /health Liveness check

Project Structure

ARGUS/
├── backend/
│   ├── app/
│   │   ├── engine/      orchestrator · reasoner · scorer · graph_builder · state · target_profile
│   │   ├── layers/      base · xlayer (cross-layer queries)
│   │   │                web + web_payloads   (L1 · OWASP Web Top 10 taxonomy)
│   │   │                llm_probe · rag_poison · mcp_agent · network
│   │   │                supply_chain · multi_agent · identity   (L2–L8)
│   │   ├── terminal/    whitelist · PTY/subprocess bridge · audit log
│   │   ├── routers/     analyze · session · report · terminal
│   │   ├── kb/          OWASP + MITRE YAML · vuln_db · manifest parser
│   │   ├── models/      Finding · Chain · StreamEvent · Session
│   │   └── main.py      FastAPI app + CORS + /health
│   └── tests/           per-layer units · web_payloads · taxonomy · chain-matching · integration
├── frontend/
│   └── src/
│       ├── pages/       Landing · Onboarding · Dashboard · TerminalView
│       ├── components/  graph · reasoning · heatmap · report · timeline · terminal · shell
│       ├── lib/         api · types · findingKb (OWASP/MITRE knowledge base) · view
│       └── store/       Zustand session store + SSE event stream
└── docker-compose.yml

CI/CD & Operations

flowchart LR
    DEV["Push / PR"] --> CI["CI<br/>backend pytest +<br/>frontend typecheck & build"]
    MAIN["Merge to main"] --> CD["CD<br/>Render deploy hook"]
    CD --> RENDER["Render backend redeploy"]
    MAIN --> VERCEL["Vercel frontend auto-deploy"]
    SCHED1["every 10 min"] --> KEEP["Keep Alive → /health"]
    SCHED2["hourly"] --> MON["Health Monitor"]
    SCHED3["push + weekly"] --> SEC["Security Scan<br/>pip-audit + npm audit"]

    classDef gh fill:#24292e,stroke:#fff,color:#fff
    class CI,CD,KEEP,MON,SEC gh
Loading
Workflow Trigger What it does
CI every push / PR Backend pytest + frontend typecheck & Vite build
CD push to main Triggers Render redeploy via deploy hook
Keep Alive every 10 min Pings /health to prevent Render cold starts
Health Monitor hourly Checks backend /health + frontend URL
Security Scan push to main + weekly pip-audit (Python) + npm audit (Node)

Security & Ethics

ARGUS is built for authorized security testing only. Reason about and test only systems you own or have explicit written permission to assess. Layer 1's active probes send real (but non-destructive, GET-only, rate-limited, time-capped) payloads; the terminal is restricted to a non-destructive recon whitelist with exploit flags blocked. You are responsible for staying within authorization. Secrets (.env) and runtime data (data/) are git-ignored and must never be committed.


Deployment

Service Platform Notes
Backend API Render Docker, persistent /data disk, Starter plan (WebSocket), health check /health
Frontend Vercel Static SPA, auto-deploys on push to main

Render env: GEMINI_API_KEY, ALLOWED_ORIGINS (Vercel URL), DATA_DIR=/data, SESSION_TTL_HOURS, LOG_LEVEL. Vercel env: VITE_API_URL (https://…onrender.com), VITE_WS_URL (wss://…onrender.com).

Required GitHub secrets: RENDER_BACKEND_URL, RENDER_DEPLOY_HOOK_URL, VERCEL_FRONTEND_URL, GEMINI_API_KEY.


License

MIT © 2026 Vethamithran

About

ARGUS — Adversarial Reasoning & Graph-based Unified Security Framework

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages