CHAD is a lightweight, Sigma-first detection engine designed for teams who store logs in OpenSearch but don't want the cost, complexity, or lock-in of a traditional SIEM.
It focuses on one thing and does it well:
Turn log events into high-quality security alerts using Sigma rules.
CHAD is not a full SIEM. It intentionally fills the gap between cheap log storage and expensive, heavyweight SIEM platforms.
Many security teams today:
- Already ship logs to OpenSearch or Elasticsearch
- Use it as a data lake because it's cheaper and more flexible
- Still need real detections, not just dashboards
Existing options usually fall into one of these traps:
| Approach | Problem |
|---|---|
| Full SIEMs (Splunk, Sentinel) | High cost, vendor lock-in |
| Scheduled query alerting | Noisy, hard to manage, delayed |
| Built-in "Security Analytics" | Immature, inflexible, limited Sigma support |
CHAD bridges that gap by providing a dedicated detection engine that sits on top of OpenSearch.
- A Sigma-native detection engine
- Designed for OpenSearch users
- Event-driven and near real-time
- API-first and automation-friendly
- Focused on alert quality and rule hygiene
- A full SIEM
- A log storage platform
- A UEBA or SOAR system
- A replacement for dashboards or investigations
CHAD assumes your logs already exist in OpenSearch and focuses purely on detection.
All detections are authored in Sigma - the open, vendor-neutral detection format.
Sigma rules are:
- Portable across platforms
- Widely understood by security engineers
- Version-controlled like code
CHAD converts Sigma rules into OpenSearch query DSL using pySigma and stores them as percolators.
CHAD uses OpenSearch percolators for detection - a reversal of normal search:
| Normal Search | Percolation |
|---|---|
| Store documents | Store queries (rules) |
| Run queries against them | Send a document (event) |
| Get matching documents | Get matching rules |
This is a natural fit for security detections.
Why percolators?
- No custom query engine to maintain
- Matching semantics identical to OpenSearch searches
- OpenSearch efficiently pre-filters candidate rules
- Rules are centrally stored and searchable
- CHAD remains stateless and easy to operate
┌─────────────┐
│ Fluentd │
└──────┬──────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ │
┌─────────────┐ ┌─────────────┐ │
│ OpenSearch │ │ CHAD │ │
│ (storage) │ │ (detect) │ │
└─────────────┘ └──────┬──────┘ │
│ │
┌───────▼────────┐ │
│ Percolate API │ │
└───────┬────────┘ │
│ │
┌───────▼────────┐ │
│ Alerts │◄────┘
│ (OpenSearch) │
└───────┬────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌────────┐ ┌─────────┐ ┌─────────┐
│Webhooks│ │ Jira │ │ Email │
└────────┘ └─────────┘ └─────────┘
- Fluentd ships logs to both OpenSearch (storage) and CHAD (detection)
- CHAD authenticates the request using per-index-pattern auth tokens
- CHAD percolates each event against deployed rules
- Matching rules generate alerts with full log context
- Alerts are enriched with threat intelligence and GeoIP
- Notifications fire via webhooks, Jira, or other integrations
- Monaco YAML Editor with Sigma schema validation and autocomplete
- Field Validation against actual OpenSearch index mappings
- Version History with diff view and one-click rollback
- SigmaHQ Integration - browse, search, and bulk import community rules
- Rule Testing against sample logs before deployment
- Real-time Matching via OpenSearch percolators
- Threshold Alerting - count-based aggregation (e.g., 10 failed logins in 5 minutes)
- Correlation Rules - multi-event detection patterns
- Exception Rules - tune out false positives without disabling rules
- Threat Intelligence - CrowdStrike, MISP, VirusTotal, AbuseIPDB
- IOC Extraction - automatic extraction of IPs, domains, hashes, URLs
- GeoIP Enrichment - geographic context for IP addresses
- MITRE ATT&CK Coverage Map - visualize detection gaps
- Health Monitoring - per-index-pattern latency and error tracking
- Audit Log - complete history of all user actions
- Bulk Operations - enable, disable, delete multiple rules at once
- Role-Based Access Control - Admin, Analyst, Viewer roles
- SSO Support - OIDC and SAML integration
- Per-Index Auth Tokens - secure log shipping authentication
- IP Allowlists - restrict which sources can send logs
- Docker and Docker Compose
- An existing OpenSearch cluster
- A log shipper (Fluentd, Logstash, etc.)
git clone https://github.com/terrifiedbug/chad.git
cd chad
cp .env.example .envEdit .env with secure values:
POSTGRES_PASSWORD=your-secure-password
JWT_SECRET_KEY=$(openssl rand -base64 32)
SESSION_SECRET_KEY=$(openssl rand -base64 32)
CHAD_ENCRYPTION_KEY=$(openssl rand -base64 32)
APP_URL=https://chad.example.comdocker compose up -dOpen http://localhost and complete:
- Create Admin Account
- Configure OpenSearch Connection
- Create First Index Pattern
Logs must be sent to both CHAD (for detection) and OpenSearch (for storage).
Fluentd Example:
<match winlogbeat.**>
@type copy
<!-- Send to CHAD for real-time detection -->
<store>
@type http
endpoint https://chad.example.com/api/logs/winlogbeat
headers {"Authorization": "Bearer YOUR_INDEX_PATTERN_AUTH_TOKEN"}
json_array true
<buffer>
@type memory
flush_interval 1s
</buffer>
</store>
<!-- Send to OpenSearch for storage -->
<store>
@type opensearch
host opensearch.example.com
port 9200
index_name winlogbeat-%Y.%m.%d
</store>
</match>Get your auth token from: Index Patterns → [Your Pattern] → Settings → Auth Token
| Good Fit | Not Ideal |
|---|---|
| Security teams using OpenSearch | Teams wanting an all-in-one SIEM |
| Organizations priced out of traditional SIEMs | Environments without a log data lake |
| Engineers who want detection-as-code | Purely GUI-driven security operations |
| Teams that value Sigma portability | Teams needing built-in UEBA |
- Detection first - one job, done well
- Simple over clever - easy to understand and operate
- Sigma everywhere - portable, vendor-neutral rules
- OpenSearch as a partner - leverage what it does best
- Make the common case easy - and the complex case possible
Most settings are managed through the web UI after initial setup.
| Variable | Required | Description |
|---|---|---|
POSTGRES_PASSWORD |
Yes | Database password |
JWT_SECRET_KEY |
Yes | JWT signing key |
SESSION_SECRET_KEY |
Yes | Session encryption key |
CHAD_ENCRYPTION_KEY |
Yes | Credential encryption key |
APP_URL |
Yes | Public URL for CSRF, SSO redirects |
CHAD_SSO_ONLY |
No | Set true to disable local login |
LOG_LEVEL |
No | Logging verbosity (default: warning) |
- OpenSearch - connection, credentials, SSL
- Index Patterns - log sources, field mappings, auth tokens
- Notifications - webhooks, Jira integration
- Threat Intelligence - API keys for TI providers
- Authentication - SSO (OIDC/SAML) configuration
- AI Mapping - Ollama, OpenAI, or Anthropic for field mapping suggestions
# Start development environment
docker compose -f docker-compose.dev.yml up -d
# Run backend tests
docker compose -f docker-compose.dev.yml run --rm backend pytest
# Run frontend tests
docker compose -f docker-compose.dev.yml run --rm frontend npm test
# Linting
docker compose -f docker-compose.dev.yml run --rm backend ruff check .
docker compose -f docker-compose.dev.yml run --rm frontend npm run lintFull documentation available at: docs.chad.terrifiedbug.com
CHAD is under active development. Contributions, feedback, and design discussions are welcome.
MIT License - see LICENSE for details.