-
Notifications
You must be signed in to change notification settings - Fork 0
Security
How Argus is secured, what is exposed, and how to deploy it safely. For reporting a vulnerability, see SECURITY.md (private advisory via the GitHub Security tab, or email).
| Surface | Default | Gate |
|---|---|---|
Bot /metrics
|
open | scrape-only aggregate data; keep open for Prometheus, restrict at the network if needed |
Bot dashboard / + /api/*
|
open | set dashboard_auth_token (or ARGUS_DASHBOARD_AUTH_TOKEN) |
Bot /healthz
|
open | liveness only |
| Fleet control plane (all routes) | refuses to start on a public bind without a token |
ARGUS_FLEET_TOKEN (or split ingest/viewer), /healthz + /readyz open |
guild_id, user_id, and channel_id are never Prometheus labels - enforced
by a test, not convention. Per-entity questions go only to the optional analytical
path (ClickHouse), which is separate storage and fails closed without a token. The
fleet control plane reads aggregate metrics only and cannot expose per-entity data.
- Set
dashboard_auth_tokenfor anything not strictly localhost. It gates/and every/api/*route with a constant-time comparison;/metrics//healthzstay open so a scraper does not need the token. - The browser remembers a
?token=link in localStorage. Query-string tokens can land in proxy/access logs; prefer theAuthorization: Bearerheader for programmatic clients, and treat the link as a credential. - Disable the UI entirely with
dashboard=Falseand rely on Grafana if you only want scraping.
Secure-by-default and hardened (see Fleet for the full table):
-
Refuse-insecure bind: a non-loopback bind with no token will not start. Set
a token, bind loopback, or
ARGUS_FLEET_INSECURE=1(local testing only). -
Split tokens (optional): a low-privilege
ARGUS_FLEET_INGEST_TOKENlives on every bot; anARGUS_FLEET_VIEWER_TOKENgates the UI/read APIs - so a leaked bot token cannot read the dashboard. Each falls back to the shared token.*_FILEvariants read from mounted secrets. -
Abuse resistance: request body cap (413), per-IP register and per-identity
heartbeat rate limits (429), and a
ARGUS_FLEET_MAX_CLUSTERScap. -
Scanner/fingerprint reduction: the version banner is stripped and security
headers (
X-Frame-Options: DENY, CSP,nosniff,Referrer-Policy) are sent on every response; unknown paths and bad tokens get flat, detail-free responses. - Single writer: an advisory lock on the state file refuses a second instance; the on-disk state is schema-versioned (unknown versions refuse to load).
-
Duplicate-identity detection: a
CLUSTER_ID/fleet_idreused from two hosts incrementsargus_fleet_identity_conflicts_totaland logs a warning. - Fail-open member: the bot's heartbeat is bounded and never raises into the bot loop, so a fleet outage cannot affect your bot.
You do not need CORS for the bundled, same-origin fleet UI - the browser only
ever talks to the control plane, which serves both the SPA and the API. Hosting the
bot and the dashboard on different machines/providers does not change this. CORS is
only needed if you serve the SPA from a different origin than the API; then set
ARGUS_FLEET_CORS_ORIGINS to an explicit allowlist (never a wildcard on a
token-gated surface).
-
Terminate TLS at a reverse proxy (or a tunnel) for any public deployment;
tokens are bearer credentials. Behind a proxy, set
ARGUS_FLEET_TRUSTED_PROXY=1so rate limits key on the real client IP, and addStrict-Transport-Securityat the proxy. -
Run as non-root. The published images already do (uid 10001) and ship a
HEALTHCHECK; the k8s example uses a read-only root filesystem and drops all capabilities. -
Restrict exposure. IP-allowlist or VPN-gate the control plane where possible;
a non-default port and
/metricsbehind the token trim opportunistic scanning. - Pin versions of the package and images so a mid-development change cannot reach a deployment.
-
Secrets: use
*_TOKEN_FILE/ Kubernetes Secrets rather than inline env vars where you can; never commit tokens.
- Releases publish to PyPI via OIDC Trusted Publishing with attestations (no stored long-lived credentials).
- The GHCR images (
argus,argus-fleet) ship an SBOM and max provenance attestation. - CodeQL and Dependabot run on the repository.