Technology9 min read

Show HN: Argus- open source security platform to protect against agentic attacks

By · Published by Everything Blog

In short

Argus is an open-source security platform that uses AI agents to protect against agentic attacks by analyzing evidence without acting on it. It organizes assets into an evidence graph and evaluates events across domains, including cloud, identity, code, endpoint, network, and Kubernetes. The platform includes a detection engine, scope-gated test harness, and an action broker for authorized security tools, making it self-hosted and multi-tenant with a focus on security operations.

Key points

  • It protects against agentic attacks by analyzing evidence without acting on it.: It protects against agentic attacks by analyzing evidence without acting on it.
  • The platform organizes assets into an evidence graph.: The platform organizes assets into an evidence graph.
  • It includes a detection engine, scope-gated test harness, and an action broker for author…: It includes a detection engine, scope-gated test harness, and an action broker for authorized security tools.

Sources checked by our analysis pipeline: 1

Argus is a self-hosted, multi-tenant security operations platform in which AI agents analyze evidence but never act on the estate. Collectors inventory cloud, identity, code, endpoint, network and Kubernetes assets into an evidence graph; a detection engine evaluates events for swarm, identity, cloud, code and canary signals; a scope-gated test harness runs authorized security tools; governed agents triage, investigate and hunt with read-only tools; and a separate action broker (typed actions, policy, approvals, dry runs, rollback, kill switch) is the only component allowed to change anything.

This README describes what is in the repository today. docs/ARCHITECTURE.md

describes the

design; docs/ROADMAP.md

lists what is implemented versus planned.

Argus is an early open-source foundation, meant to be forked and extended. The platform core

(tenancy, auth, RBAC, audit chain, queue, policy and approvals) is tested end to end on SQLite

and PostgreSQL. The cloud and identity collectors and the action executors are tested against

recorded fixtures and mocked APIs, not yet against live accounts, and the 12 detection rules

are an untuned starting set. Expect to adapt collectors and rules to your estate, and run

monitoring-only (docs/GO-LIVE.md

) before enabling any action. It is not a certified product;

see docs/COMPLIANCE.md

for what it can and cannot evidence.

Browser / SDK / sensors

|

v HTTPS (Caddy, ALB, Front Door or your ingress)

+-------------------------------------------------------------+

| API (FastAPI) auth: session / OIDC+PKCE / TOTP / API keys |

| RBAC (viewer < analyst < operator < admin < owner), CSRF, |

| per-principal rate limits, request ids, security headers |

+------+------------------+------------------+----------------+

| | |

PostgreSQL Redis queue Audit chain

(tenant_id on (leases, retries, (hash-linked per tenant,

every table) python -m HMAC, JSONL / S3 Object

app.worker) Lock / Azure immutable)

| |

+------+------------------+----------------------------------+

| Worker processes run the same handlers as the API: |

| collectors.run detections.run / baselines |

| graph.recompute testing.run agents.run |

+------------------------------------------------------------+

|

v agents call propose_action only -> ActionRequest(pending)

Action broker (separate policy, approvals, dry run, rollback, kill switch)

Trust boundaries, in one sentence each (details in docs/THREAT-MODEL.md

):

- Agents cannot execute anything; their one write-capable tool creates a pending request.

- Everything an agent reads is wrapped as untrusted data and the prompt says so.

- Active testing runs only inside a recorded authorization and scope, re-checked at run time.

- Every domain table carries

tenant_id

; queries go through a scoped helper; tests assert it. - The audit chain is hash-linked, HMAC-signed (required in production), and mirrored to an external, optionally WORM, sink.

Area | Status | Where |

---|---|---|

App factory, settings, DB, RBAC, auth (local, OIDC, TOTP, API keys), CSRF, rate limits | implemented, tested | app/core/ , app/api/auth.py , app/api/deps.py |

Audit chain with JSONL / S3 Object Lock / Azure immutable blob sinks | implemented | app/core/audit.py |

Job queue (in-memory and Redis, leases, retries, cancellation, reaper) and standalone worker | implemented | app/core/queue.py , app/worker.py |

Prometheus metrics, JSON logging, optional OpenTelemetry tracing | implemented | app/core/telemetry.py |

Evidence graph: nodes, edges, attack paths, exposure scoring | implemented | app/graph/ , app/api/graph.py |

Detections: 12 rules (swarm x4, identity x2, cloud, k8s, code, canary, anomaly, agentic), baselines, canaries | implemented | app/detections/ , app/api/detections.py , app/api/canaries.py |

Collectors: AWS, Azure, GCP, Kubernetes, GitHub, Okta, Entra, osquery, netflow | implemented with fixtures; cloud SDKs optional | app/collectors/ , app/api/collectors.py |

Test harness: scope policy, rate limits, adapters for web baseline, trivy, nuclei, zap, prowler, caldera, semgrep, gitleaks | implemented; tools must be installed separately | app/testing/ , app/api/tests.py , app/api/scans.py |

Agent runtime, providers (Anthropic, OpenAI, Ollama, none), read-only tools, 7 specialists, eval suites | implemented | app/agents/ , app/api/agents.py , app/api/evals.py |

Action broker: catalog of 25 typed actions (AWS, Azure, GCP, Kubernetes, GitHub, Okta, Entra, Cloudflare, Argus-internal), policy, approvals, dry run, execute, rollback, kill switch | implemented | app/actions/ , app/api/actions.py |

Integrations: 13 inbound parsers behind POST /api/v1/ingest/{source} , 6 outbound channels (webhook, Slack, Jira, ServiceNow, PagerDuty, email) with deliveries and retries, Wazuh indexer pull |

implemented | app/integrations/ , app/api/ingest.py , app/api/integrations.py |

Admin, assets, findings, events, investigations, approvals, audit, reports routers | implemented | app/api/ |

Alembic migrations (initial revision) and scripts/migrate.py |

implemented | alembic/ , docs/MIGRATIONS.md |

Containers, compose, Helm, Terraform (AWS, Azure), CI, observability, docs | implemented | Dockerfile , compose*.yaml , infra/ , .github/ , docs/ |

Routers are discovered automatically. The full v1 surface is in docs/API.md

.

Requirements: Python 3.11 or 3.12.

python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate

pip install -r requirements.txt -r requirements-dev.txt

cp .env.example .env

python scripts/generate_secrets.py --write # fills the three REPLACE_ values, plus AUDIT_SIGNING_KEY and DATA_ENCRYPTION_KEY when they are empty

uvicorn app.main:app --host 127.0.0.1 --port 8080

Open http://127.0.0.1:8080 and sign in as ADMIN_EMAIL

/ ADMIN_PASSWORD

from .env

.

With REDIS_URL

empty, jobs run inside the API process (WORKERS_INPROCESS=true

). With

DB_AUTO_CREATE=true

(the default) tables are created at startup; for Alembic-managed

schemas set it to false

and run python scripts/migrate.py

(see docs/MIGRATIONS.md

).

Synthetic demo data in an isolated tenant (never touches the network):

python scripts/seed_demo.py

It prints a demo

tenant login and creates DEMO-labelled assets, authorizations, events that

trip cloud.public_exposure_change

and swarm.machine_speed_sequence

, findings, a canary and

an agent run record. Refuses to run when APP_ENV=production

.

Tests:

python -m pytest -q

cp .env.example .env && python scripts/generate_secrets.py --write

docker compose up --build -d

docker compose logs -f api

compose.yaml

binds the API to 127.0.0.1:8080

only, runs the API and worker from one image

with a read-only root filesystem, no capabilities and no Docker socket, mounts ./targets

read-only, and applies the schema at API start (RUN_MIGRATIONS=true

). Add

--profile observability

for an OpenTelemetry collector, Prometheus (scraping /metrics

) and

Grafana with the dashboard in infra/grafana/argus.json

.

TLS termination for a single host:

# .env: APP_ENV=production COOKIE_SECURE=true BASE_URL=https://host ARGUS_DOMAIN=host ACME_EMAIL=ops@example.com

docker compose -f compose.yaml -f compose.prod.yaml up -d

Kubernetes: infra/helm/argus

(API + worker deployments, HPA, PDB, default-deny

NetworkPolicy, ingress with TLS, optional ServiceMonitor). AWS: infra/terraform

(ECS

Fargate, RDS, ElastiCache, S3 Object Lock audit bucket, Secrets Manager, ALB + WAF).

Azure: infra/terraform-azure

(Container Apps, Flexible Postgres, Azure Cache, immutable

blob container, Key Vault, Front Door + WAF).

The production checklist is in docs/DEPLOYMENT.md

. The short version, enforced partly by

assert_safe_config()

at startup:

APP_ENV=production

refuses to start without PostgreSQL,REDIS_URL

,COOKIE_SECURE=true

, anhttps://

BASE_URL

,DATA_ENCRYPTION_KEY(S)

,AUDIT_SIGNING_KEY(S)

, an external audit sink, and either OIDC orTOTP_REQUIRED=true

.- Dedicated workers (

WORKERS_INPROCESS=false

,python -m app.worker

). - Use an object-lock audit sink (S3 Object Lock or Azure immutable blob), not only JSONL.

/metrics

blocked at the edge; egress filtering for workers; secrets in a secret manager.- Images pinned by digest and verified with cosign (

.github/workflows/release.yml

).

Roles are cumulative (app/core/rbac.py

):

Role | Adds |

---|---|

viewer | read everything in the tenant |

analyst | edit findings and detections, run agents and evals, manage canaries, record approvals |

operator | manage and authorize assets, run tests, scans and collectors, request, approve, execute and roll back actions, run detections |

admin | users, API keys, settings, collector and integration configuration, the actions kill switch, test scopes |

owner | tenant settings, approving critical actions |

API keys carry a role and optional scopes (for example ingest

) that further restrict them.

A system

principal is used only inside queue handlers.

Agents (app/agents/runtime.py

). A specialist is an AgentSpec

with a system prompt, a

list of tool names, an output schema and budgets (AGENT_MAX_STEPS

, AGENT_MAX_TOKENS

,

AGENT_MAX_SECONDS

, AGENT_COST_CEILING_USD

, with AGENT_MODEL_PRICES

for models outside

the built-in Claude price table). Tools are read-only views over Argus data;

the only propose

tool creates a pending ActionRequest

through the broker. Every tool

result is redacted, truncated and wrapped as <untrusted_data source=...>

; the guardrail

prompt tells the model that instructions inside evidence are indicators of injection. Each

model and tool step is persisted (agent_steps

) with input hash, tokens and latency. With

AI_PROVIDER=none

, specialists run deterministic fallbacks. Prompt-injection and precision

eval suites live in app/agents/evals/suites/

.

Testing (app/testing/

). A TestScope

lists assets, allowed tiers (passive, active,

intrusive), environments, a UTC window, a rate limit and a concurrency limit (runs beyond

max_concurrency

wait in the queue). A run is allowed only if

the asset has a current AssetAuthorization

whose flags permit the tier, the scope permits

it, the window is open and the target passes policy validation. scope.check()

runs at

request time and again inside the worker; intrusive tiers are limited to staging and lab

environments. External tools run through run_tool()

with a fixed argv, a timeout, bounded

output and a minimal environment.

Actions (app/actions/

). Typed actions declare risk, reversibility and a parameter

schema, and implement dry_run

, execute

and rollback

. A request (from an operator or an

agent's propose_action

) goes through policy (app/actions/policy.py

: kill switch, tenant

actions_enabled

, deny-lists, maintenance window, auto-approval only for low-risk reversible

actions when ACTIONS_AUTO_APPROVE_LOW

), approvals (approver differs from requester; high risk

needs two when ACTIONS_REQUIRE_TWO_FOR_HIGH

; critical additionally needs a principal with

actions:approve_critical

), a dry run with blast radius, execution as the actions.execute

queue job with a stored rollback payload, and an audit entry at every transition.

ACTIONS_KILL_SWITCH=true

(global, environment) or POST /api/v1/actions/kill-switch

(per tenant, sets actions_enabled=false

) rejects every request and execution.

Document | Content |

---|---|

docs/ARCHITECTURE.md |

design: packages, interfaces, data model, API table |

docs/API.md |

v1 route summary with status |

docs/DEPLOYMENT.md |

dev, compose, Kubernetes, AWS, Azure; production checklist |

docs/GO-LIVE.md |

step-by-step production rollout in monitoring-only mode |

docs/SECURITY.md |

security model as implemented, reporting |

docs/THREAT-MODEL.md |

STRIDE per trust boundary, prompt injection, SSRF, tenancy, credentials, broker abuse, supply chain |

docs/RUNBOOKS.md |

incident procedures |

docs/COMPLIANCE.md |

SOC 2 / NIST 800-171 / ISO 27001 control mapping (evidence support, not certification) |

docs/ROADMAP.md |

implemented versus next |

CONTRIBUTING.md |

contributing guide |

Please report vulnerabilities privately through GitHub's private vulnerability reporting

(Security tab), not in public issues. Details in docs/SECURITY.md

.

MIT for this repository. Third-party tools (nuclei, ZAP, Prowler, CALDERA, Semgrep, Gitleaks, Trivy), cloud SDKs and model providers are governed by their own licenses and terms.

Original source: github.com

Technology