Config Schema Reference¶
lumen-argus loads configuration from YAML files in the following order:
- Global config:
~/.lumen-argus/config.yaml(created automatically on first run) - Project config:
.lumen-argus.yamlin the current working directory (optional, can only be more restrictive)
The config uses PyYAML (yaml.safe_load) for full YAML 1.1 spec support including anchors, aliases, block scalars, and flow mappings.
Top-level keys¶
| Key | Type | Default | Description |
|---|---|---|---|
version |
str |
"1" |
Config schema version. |
default_action |
str |
alert |
Default action when a finding has no detector-specific override. One of: log, alert, redact, block. |
proxy¶
Network and connection settings for the proxy server.
| Key | Type | Default | Description |
|---|---|---|---|
proxy.port |
int |
8080 |
Port to listen on. Range: 1--65535. |
proxy.bind |
str |
127.0.0.1 |
Bind address. Only 127.0.0.1 and localhost are allowed (enforced at runtime). |
proxy.timeout |
int |
120 |
Socket timeout in seconds for upstream connections. Range: 1--300. |
proxy.retries |
int |
1 |
Number of retry attempts on upstream connection failure. Range: 0--5. |
proxy.max_body_size |
int |
52428800 |
Maximum request body size in bytes to scan (50 MB). Bodies larger than this are forwarded without scanning. |
proxy.max_connections |
int |
10 |
Maximum concurrent upstream connections. Additional requests queue until a slot opens. Range: 1--100. |
proxy.drain_timeout |
int |
30 |
Seconds to wait for in-flight requests to complete during shutdown. Range: 0--300. |
proxy.ca_bundle |
str |
"" |
Path to a custom CA certificate file or directory. Use this behind corporate proxies. Empty string uses system defaults. |
proxy.verify_ssl |
bool |
true |
Verify upstream TLS certificates. Set to false only for development/testing. |
proxy.standalone |
bool |
true |
Whether the proxy is running standalone. Set to false when managed by tray app. Also settable via --no-standalone CLI flag. Exposed in /api/v1/status. |
proxy:
port: 8080
bind: "127.0.0.1"
timeout: 120
retries: 1
max_body_size: 52428800
max_connections: 10
drain_timeout: 30
ca_bundle: ""
verify_ssl: true
standalone: true
Do not disable SSL verification in production
Setting proxy.verify_ssl: false disables all TLS certificate checks. This should only be used in local development or testing environments.
detectors¶
Per-detector configuration. Each detector (secrets, pii, proprietary) accepts the same set of keys.
| Key | Type | Default | Description |
|---|---|---|---|
detectors.<name>.enabled |
bool |
true |
Whether the detector is active. |
detectors.<name>.action |
str |
(uses default_action) |
Action override for this detector. One of: log, alert, redact, block. Empty string falls back to default_action. |
detectors.secrets.entropy_threshold |
float |
4.5 |
Shannon entropy threshold (bits/char) for the entropy sweep in the secrets detector. Range: 0.0--10.0. |
detectors:
secrets:
enabled: true
action: alert
entropy_threshold: 4.5
pii:
enabled: true
action: alert
proprietary:
enabled: true
action: alert
Redact action in Community Edition
In the Community Edition, the redact action is automatically downgraded to alert. Full redaction requires a Pro license.
allowlists¶
Values and paths that should never be flagged. See the Allowlists guide for detailed usage.
| Key | Type | Default | Description |
|---|---|---|---|
allowlists.secrets |
list[str] |
[] |
Secret values or glob patterns to skip. Supports exact match and fnmatch globs. |
allowlists.pii |
list[str] |
[] |
PII values or glob patterns to skip. |
allowlists.paths |
list[str] |
[] |
File path glob patterns. Matching source files are excluded from scanning entirely. |
allowlists:
secrets:
- "AKIAIOSFODNN7EXAMPLE"
- "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
pii:
- "*@example.com"
- "*@test.local"
paths:
- "test/**"
- "tests/**"
- "fixtures/**"
custom_rules¶
User-defined regex detection rules. Each rule is a list entry with the following keys:
| Key | Type | Default | Description |
|---|---|---|---|
name |
str |
(required) | Unique identifier for the rule. Used in findings as the type field. |
pattern |
str |
(required) | Regular expression pattern. Compiled with Python's re module. |
severity |
str |
high |
Finding severity. One of: critical, high, warning, info. |
action |
str |
(uses default_action) |
Action override for findings from this rule. One of: log, alert, redact, block. |
custom_rules:
- name: internal_api_key
pattern: "INTERNAL-[A-Z0-9]{32}"
severity: critical
action: block
- name: todo_credential
pattern: "TODO:.*password|TODO:.*secret"
severity: warning
action: alert
Pattern validation
Invalid regex patterns are logged as warnings during config load and the rule is silently skipped. Check proxy startup logs if a custom rule does not appear to be working.
logging¶
Application log file settings (rotated log files written to disk).
| Key | Type | Default | Description |
|---|---|---|---|
logging.log_dir |
str |
~/.lumen-argus/logs |
Directory for application log files. |
logging.file_level |
str |
info |
Minimum log level written to file. One of: debug, info, warning, error. |
logging.max_size_mb |
int |
10 |
Maximum log file size in MB before rotation. |
logging.backup_count |
int |
5 |
Number of rotated log files to keep. |
audit¶
Audit log settings. Audit logs are JSONL files recording every scanned request.
| Key | Type | Default | Description |
|---|---|---|---|
audit.log_dir |
str |
~/.lumen-argus/audit |
Directory for audit JSONL files. Files are created with 0o600 permissions. |
audit.retention_days |
int |
90 |
Number of days to retain audit log files before automatic cleanup. |
Security note
Audit logs never contain the matched_value field from findings. Only the masked value_preview is written to disk, preventing secondary exfiltration of sensitive data through log files.
dashboard¶
Web dashboard settings. The dashboard runs on a separate port and provides a browser-based UI for viewing findings, stats, and audit logs.
| Key | Type | Default | Description |
|---|---|---|---|
dashboard.enabled |
bool |
true |
Whether to start the dashboard server. |
dashboard.port |
int |
8081 |
Port to listen on. Range: 1--65535. |
dashboard.bind |
str |
127.0.0.1 |
Bind address. Non-loopback requires --host CLI flag (for Docker). |
dashboard.password |
str |
"" |
Optional password for dashboard access. Can also be set via LUMEN_ARGUS_DASHBOARD_PASSWORD env var. Empty = open access. |
Authentication
When a password is set, the dashboard uses session-based auth with CSRF double-submit cookies. Sessions expire after 8 hours. Plugin auth providers (OAuth, SAML) can be registered via the extension API for Enterprise use.
analytics¶
SQLite analytics store settings. Powers the dashboard charts and paginated findings.
| Key | Type | Default | Description |
|---|---|---|---|
analytics.enabled |
bool |
true |
Whether to create and populate the analytics store. Only active when dashboard is enabled. |
analytics.db_path |
str |
~/.lumen-argus/analytics.db |
Path to the SQLite database file. Created with 0o600 permissions. |
analytics.retention_days |
int |
365 |
Days to retain findings before automatic cleanup. |
Pro extension
The Pro edition extends the analytics store with additional tables (notification channels, custom rules, allowlist entries, etc.) by subclassing AnalyticsStore. Community and Pro share the same SQLite file — data survives license transitions.
rule_analysis¶
Configuration for rule overlap analysis via Crossfire (optional dependency).
| Key | Type | Default | Description |
|---|---|---|---|
rule_analysis.samples |
int |
50 |
Corpus strings generated per rule. Higher = more stable results, slower analysis. Minimum 10. |
rule_analysis.threshold |
float |
0.8 |
Overlap fraction to classify as duplicate or subset (0.0–1.0). |
rule_analysis.seed |
int |
42 |
Random seed for reproducible corpus generation. |
rule_analysis.auto_on_import |
bool |
true |
Automatically run analysis after rule import (CLI and auto-import on first startup). |
Install crossfire: pip install lumen-argus[rules-analysis] or pip install git+https://github.com/lumen-argus/crossfire.git. Docker image includes it by default.
notifications¶
Notification channels managed via IaC. Reconciled to SQLite on startup and SIGHUP using Kubernetes-style declarative reconciliation — YAML is fully authoritative.
Each entry is a channel definition:
| Key | Type | Default | Description |
|---|---|---|---|
name |
str |
(required) | Unique channel name. |
type |
str |
(required) | Channel type: webhook, email, slack, teams, pagerduty, opsgenie, jira. |
events |
list[str] |
[block, alert] |
Which finding actions trigger this channel. |
min_severity |
str |
warning |
Minimum severity to dispatch. |
enabled |
bool |
true |
Whether the channel is active. |
Additional keys are type-specific (e.g., url, smtp_host, webhook_url) and stored in the channel config.
notifications:
- name: production-alerts
type: webhook
url: "https://hooks.slack.com/services/T00/B00/xxx"
events: [block, alert]
min_severity: high
- name: security-team
type: email
smtp_host: "smtp.company.com"
from_addr: "argus@company.com"
to_addrs: "security@company.com, sre@company.com"
events: [block]
min_severity: critical
Freemium model
Without a Pro license, 1 channel of any type is allowed. With Pro, unlimited. All 7 channel types are available in both tiers — Pro provides the dispatch implementations.
YAML reconciliation
YAML channels appear as read-only cards in the dashboard with a YAML badge. All fields (including enabled) are overwritten from YAML on every startup/SIGHUP. Dashboard-managed channels are never touched by the reconciler.
pipeline¶
Pipeline stage configuration. Controls which scanning stages are active and how the encoding decoder behaves. Stages can also be toggled from the Pipeline dashboard page.
pipeline.stages.<name>¶
Per-stage settings. Each stage accepts:
| Key | Type | Default | Description |
|---|---|---|---|
pipeline.stages.<name>.enabled |
bool |
(varies) | Whether the stage is active. |
pipeline.stages.<name>.action |
str |
"" |
Stage-level action override (Pro). Empty = use default_action. |
pipeline.stages.<name>.mode |
str |
"async" |
Scanning mode for response stages. async (community, zero latency) or buffered (Pro, blocks response). |
Available stages¶
| Stage | Direction | Default | Available | Description |
|---|---|---|---|---|
outbound_dlp |
Request | true |
Yes | Secret/PII/proprietary detection on outbound requests |
encoding_decode |
Request | true |
Yes | Decode base64, hex, URL, Unicode before scanning |
response_secrets |
Response | false |
Yes | Detect secrets in API responses (async, zero latency) |
response_injection |
Response | false |
Yes | Detect prompt injection in responses (async, zero latency) |
mcp_arguments |
MCP | true |
Yes | Scan MCP tool call arguments (via lumen-argus mcp) |
mcp_responses |
MCP | true |
Yes | Scan MCP tool return values (via lumen-argus mcp) |
websocket_outbound |
WebSocket | false |
Yes | Scan outbound WebSocket frames (opt-in, same port) |
websocket_inbound |
WebSocket | false |
Yes | Scan inbound WebSocket frames (opt-in, same port) |
pipeline.stages.encoding_decode (extended)¶
The encoding decode stage has additional settings:
| Key | Type | Default | Description |
|---|---|---|---|
base64 |
bool |
true |
Decode base64-encoded content before scanning. |
hex |
bool |
true |
Decode hex-encoded content before scanning. |
url |
bool |
true |
Decode URL-encoded content before scanning. |
unicode |
bool |
true |
Decode Unicode escape sequences before scanning. |
max_depth |
int |
2 |
Maximum nested encoding layers to decode (e.g., base64 inside URL-encoding). Range: 1--5. |
min_decoded_length |
int |
8 |
Ignore decoded strings shorter than this. Range: 1--100. |
max_decoded_length |
int |
10000 |
Cap decoded output size to prevent memory issues. Range: 100--1000000. |
pipeline:
stages:
outbound_dlp:
enabled: true
encoding_decode:
enabled: true
base64: true
hex: true
url: true
unicode: true
max_depth: 2
min_decoded_length: 8
max_decoded_length: 10000
response_secrets:
enabled: false # opt-in: detect secrets in API responses
mode: async # async (community) | buffered (Pro)
response_injection:
enabled: false # opt-in: detect prompt injection in responses
mode: async
Dashboard Pipeline page
All pipeline settings can be configured from the Pipeline page in the dashboard. Changes are saved to the database and applied immediately via hot-reload.
websocket¶
WebSocket proxy settings for the /ws endpoint.
| Key | Type | Default | Description |
|---|---|---|---|
websocket.max_frame_size |
int |
1048576 |
Maximum text frame size in bytes to scan (1MB). Larger frames are truncated before scanning. |
websocket.allowed_origins |
list[str] |
[] |
Allowlist of Origin headers. Empty = all origins allowed. |
mcp¶
MCP scanning proxy configuration for lumen-argus mcp.
| Key | Type | Default | Description |
|---|---|---|---|
mcp.allowed_tools |
list[str] |
[] |
Allowlist of tool names. Empty = all tools allowed. |
mcp.blocked_tools |
list[str] |
[] |
Blocklist of tool names. Takes precedence over allowlist. |
mcp.env_filter |
bool |
true |
Restrict subprocess environment to safe vars only. |
mcp.env_allowlist |
list[str] |
[] |
Additional env vars to pass through when env_filter is enabled. |
mcp.request_tracking |
bool |
true |
Confused deputy protection — track outbound request IDs. |
mcp.unsolicited_response_action |
str |
"warn" |
Action on unsolicited response: warn or block. |
mcp.scan_tool_descriptions |
bool |
true |
Scan tool descriptions for poisoning patterns. |
mcp.detect_drift |
bool |
true |
Track tool definition changes via SHA-256 baselines. |
mcp.drift_action |
str |
"alert" |
Action on tool drift: alert or block. |
mcp.session_binding |
bool |
false |
Validate tools/call against first tools/list inventory (opt-in). |
mcp.unknown_tool_action |
str |
"warn" |
Action on unknown tool: warn or block. |
mcp:
allowed_tools: [] # empty = all allowed
blocked_tools:
- execute_command
- run_shell
env_filter: true
request_tracking: true
scan_tool_descriptions: true
detect_drift: true
drift_action: alert
session_binding: false
relay¶
Configuration for the relay process in fault-isolated mode.
| Key | Type | Default | Description |
|---|---|---|---|
relay.port |
int |
8080 |
Relay listening port. |
relay.fail_mode |
str |
open |
Action when engine is down. open = forward directly to upstream. closed = return 503. |
relay.engine_url |
str |
http://localhost:8090 |
Engine process URL. |
relay.health_check_interval |
int |
2 |
Seconds between engine health checks. |
relay.health_check_timeout |
int |
1 |
Seconds before a health check times out. |
relay.queue_on_startup |
int |
2 |
Seconds to buffer requests while engine starts. |
relay:
port: 8080
fail_mode: open
engine_url: http://localhost:8090
health_check_interval: 2
health_check_timeout: 1
queue_on_startup: 2
engine¶
Configuration for the engine process in fault-isolated mode.
| Key | Type | Default | Description |
|---|---|---|---|
engine.port |
int |
8090 |
Engine listening port. |
enrollment¶
Enterprise agent deployment configuration. Served to agents via GET /api/v1/enrollment/config (Pro).
| Key | Type | Default | Description |
|---|---|---|---|
enrollment.organization |
str |
"" |
Organization name displayed in tray app ("Protected by Acme Corp"). |
enrollment.proxy_url |
str |
"" |
Proxy URL that agents configure AI tools to use. Empty = derived from proxy.bind:proxy.port. |
enrollment.dashboard_url |
str |
"" |
Dashboard URL for agent poller/SSE. Empty = derived from dashboard.bind:dashboard.port. |
enrollment.ca_cert |
str |
"" |
PEM content or path to CA certificate for TLS inspection proxies. |
enrollment.policy.fail_mode |
str |
open |
What happens when proxy is unreachable: open (direct to upstream) or closed (block). |
enrollment.policy.auto_configure |
bool |
true |
Force-configure all detected AI tools (no per-tool opt-out). |
enrollment.policy.allow_disable_protection |
bool |
true |
Whether developers can toggle protection off. |
enrollment.policy.telemetry_interval_seconds |
int |
300 |
How often agents send heartbeats (minimum 60). |
enrollment.policy.watch_interval_seconds |
int |
300 |
How often agents scan for new tools (minimum 60). |
enrollment:
organization: "Acme Corp"
proxy_url: "https://argus.corp.io:8080"
dashboard_url: "https://argus.corp.io:8081"
policy:
fail_mode: closed
auto_configure: true
allow_disable_protection: false
telemetry_interval_seconds: 300
watch_interval_seconds: 300
Full config example¶
version: "1"
proxy:
port: 8080
bind: "127.0.0.1"
timeout: 120
retries: 1
max_body_size: 52428800
max_connections: 10
drain_timeout: 30
ca_bundle: ""
verify_ssl: true
standalone: true
default_action: alert
detectors:
secrets:
enabled: true
action: alert
entropy_threshold: 4.5
pii:
enabled: true
action: alert
proprietary:
enabled: true
action: alert
allowlists:
secrets:
- "AKIAIOSFODNN7EXAMPLE"
pii:
- "*@example.com"
paths:
- "test/**"
- "tests/**"
custom_rules:
- name: internal_api_key
pattern: "INTERNAL-[A-Z0-9]{32}"
severity: critical
action: block
pipeline:
stages:
outbound_dlp:
enabled: true
encoding_decode:
enabled: true
base64: true
hex: true
url: true
unicode: true
max_depth: 2
min_decoded_length: 8
max_decoded_length: 10000
dashboard:
enabled: true
port: 8081
bind: "127.0.0.1"
password: ""
# notifications:
# - name: production-alerts
# type: webhook
# url: "https://hooks.slack.com/services/T00/B00/xxx"
# events: [block, alert]
# min_severity: high
analytics:
enabled: true
db_path: "~/.lumen-argus/analytics.db"
retention_days: 365
rule_analysis:
samples: 50
threshold: 0.8
seed: 42
auto_on_import: true
logging:
log_dir: "~/.lumen-argus/logs"
file_level: info
max_size_mb: 10
backup_count: 5
audit:
log_dir: "~/.lumen-argus/audit"
retention_days: 90