Alerting
Sentinel includes a built-in alerting system that sends real-time notifications when security events occur. Alerts are dispatched to one or more providers — Slack, email, or a custom webhook — whenever a threat event meets or exceeds your configured severity threshold. This lets your security team respond immediately to attacks without watching the dashboard around the clock.
Pipeline Integration
Alert Providers
Sentinel supports three alert providers out of the box. You can enable any combination of them — all three can run simultaneously.
| Provider | Channel | Description |
|---|---|---|
| Slack | slack | Sends rich formatted messages to a Slack channel via an incoming webhook URL. |
email | Sends HTML-formatted alert emails via SMTP to one or more recipients. | |
| Webhook | webhook | Sends a JSON payload via HTTP POST to any custom URL, with optional custom headers. |
Configuration
Alerting is configured through the Alerts field on the main sentinel.Config struct. Each provider is enabled by providing its corresponding config pointer — nil means the provider is disabled.
AlertConfig
| Field | Type | Default | Description |
|---|---|---|---|
MinSeverity | Severity | High | Minimum severity level required to trigger an alert. Events below this threshold are silently ignored. |
Slack | *SlackConfig | nil | Slack webhook configuration. Set to enable Slack alerts. |
Email | *EmailConfig | nil | Email SMTP configuration. Set to enable email alerts. |
Webhook | *WebhookConfig | nil | Custom webhook configuration. Set to enable webhook alerts. |
SlackConfig
| Field | Type | Description |
|---|---|---|
WebhookURL | string | The Slack incoming webhook URL. Create one at api.slack.com/messaging/webhooks. |
EmailConfig
| Field | Type | Description |
|---|---|---|
SMTPHost | string | SMTP server hostname (e.g., smtp.gmail.com). |
SMTPPort | int | SMTP server port (e.g., 587 for TLS). |
Username | string | SMTP authentication username, also used as the From address. |
Password | string | SMTP authentication password or app-specific password. |
Recipients | []string | List of email addresses to receive alerts. |
WebhookConfig
| Field | Type | Description |
|---|---|---|
URL | string | The endpoint URL that receives the JSON POST request. |
Headers | map[string]string | Optional custom HTTP headers to include with every request (e.g., authorization tokens). |
1// AlertConfig configures the alerting system.2type AlertConfig struct {3 MinSeverity Severity `json:"min_severity"`4 Slack *SlackConfig `json:"slack,omitempty"`5 Email *EmailConfig `json:"email,omitempty"`6 Webhook *WebhookConfig `json:"webhook,omitempty"`7}89// SlackConfig configures Slack webhook alerts.10type SlackConfig struct {11 WebhookURL string `json:"webhook_url"`12}1314// EmailConfig configures email alerts.15type EmailConfig struct {16 SMTPHost string `json:"smtp_host"`17 SMTPPort int `json:"smtp_port"`18 Username string `json:"username"`19 Password string `json:"password"`20 Recipients []string `json:"recipients"`21}2223// WebhookConfig configures generic webhook alerts.24type WebhookConfig struct {25 URL string `json:"url"`26 Headers map[string]string `json:"headers,omitempty"`27}
Severity Filtering
The MinSeverity field controls which threat events trigger alerts. Only events with a severity equal to or greater than the configured threshold are dispatched. Events below the threshold are silently discarded by the alert dispatcher.
| Severity | Level | Description |
|---|---|---|
Low | 1 | Minor events such as informational detections. Alerts on everything. |
Medium | 2 | Moderate events such as suspicious patterns. Skips Low events. |
High | 3 | Serious events such as confirmed attack attempts. Default threshold. |
Critical | 4 | Only the most severe events trigger alerts. Use for low-noise channels. |
Default Severity
MinSeverity is not set, it defaults to High. This means only High and Critical events trigger alerts by default. Set it to sentinel.SeverityLow if you want to be alerted on all events, but be aware this can be noisy in high-traffic environments.1// Alert on everything (noisy)2Alerts: sentinel.AlertConfig{3 MinSeverity: sentinel.SeverityLow,4 // ...providers5}67// Alert only on critical events (quiet)8Alerts: sentinel.AlertConfig{9 MinSeverity: sentinel.SeverityCritical,10 // ...providers11}
How It Works
The alert Dispatcher is registered as a handler in the Sentinel event pipeline. When any detection feature (WAF, Auth Shield, Anomaly Detection, Rate Limiting) produces a threat event, the pipeline delivers it to the dispatcher. The dispatcher then:
- Checks the severity threshold — if the event severity is below
MinSeverity, it is ignored. - Deduplicates — repeated alerts for the same IP and threat type combination are suppressed within a 5-minute window to prevent alert fatigue.
- Dispatches concurrently — the event is sent to all configured providers in parallel. A failure in one provider does not affect the others.
- Retries on failure — each provider has up to 3 attempts with exponential backoff (1s, 2s, 4s) before the alert is marked as failed.
- Records history — every dispatch attempt (success or failure) is recorded in the alert history, which is accessible via the dashboard and API.
Deduplication
Slack Integration
The Slack provider sends rich formatted messages using Slack Block Kit. Each alert includes the severity level, threat type, source IP (with country if geolocation is enabled), the targeted route, whether the request was blocked, and the timestamp.
Configuration
1sentinel.Mount(r, nil, sentinel.Config{2 WAF: sentinel.WAFConfig{3 Enabled: true,4 Mode: sentinel.ModeBlock,5 },6 Alerts: sentinel.AlertConfig{7 MinSeverity: sentinel.SeverityHigh,8 Slack: &sentinel.SlackConfig{9 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxxx",10 },11 },12})
Message Format
Slack alerts are formatted with Block Kit sections. The message includes a header with a severity indicator, a divider, and a details section:
--- Slack message ---High Threat Detected────────────────────Type: SQLInjectionIP: 203.0.113.50 (United States)Route: GET /api/users?id=1' OR '1'='1Blocked: YesTime: 2025-01-15T14:30:00Z
Slack Webhook Setup
Email Integration
The email provider sends HTML-formatted alert emails via SMTP. Each email includes the severity level, threat type, source IP, targeted route, block status, and timestamp in a styled table layout.
Configuration
1sentinel.Mount(r, nil, sentinel.Config{2 WAF: sentinel.WAFConfig{3 Enabled: true,4 Mode: sentinel.ModeBlock,5 },6 Alerts: sentinel.AlertConfig{7 MinSeverity: sentinel.SeverityHigh,8 Email: &sentinel.EmailConfig{9 SMTPHost: "smtp.gmail.com",10 SMTPPort: 587,11 Username: "alerts@yourcompany.com",12 Password: "your-app-specific-password",13 Recipients: []string{14 "security-team@yourcompany.com",15 "oncall@yourcompany.com",16 },17 },18 },19})
The email subject line follows the format: [Sentinel] High Threat: SQLInjection from 203.0.113.50. The body is an HTML table with the same details as the Slack message, styled for readability in email clients.
Gmail App Passwords
Password field.Webhook Integration
The webhook provider sends a JSON payload via HTTP POST to any URL you specify. This is ideal for integrating with custom SIEM systems, PagerDuty, Opsgenie, Datadog, or any service that accepts JSON webhooks. You can include custom headers for authentication.
Configuration
1sentinel.Mount(r, nil, sentinel.Config{2 WAF: sentinel.WAFConfig{3 Enabled: true,4 Mode: sentinel.ModeBlock,5 },6 Alerts: sentinel.AlertConfig{7 MinSeverity: sentinel.SeverityMedium,8 Webhook: &sentinel.WebhookConfig{9 URL: "https://your-siem.example.com/api/v1/events",10 Headers: map[string]string{11 "Authorization": "Bearer your-api-token",12 "X-Source": "sentinel",13 },14 },15 },16})
JSON Payload Structure
Every webhook request sends a JSON payload with the following fields:
{"event": "threat_detected","threat_id": "te-abc123","timestamp": "2025-01-15T14:30:00Z","ip": "203.0.113.50","method": "GET","path": "/api/users","threat_types": ["SQLInjection"],"severity": "High","confidence": 95,"blocked": true,"country": "United States","evidence": "1' OR '1'='1"}
| Field | Type | Description |
|---|---|---|
event | string | Always "threat_detected". |
threat_id | string | Unique identifier for the threat event. |
timestamp | string | ISO 8601 / RFC 3339 timestamp in UTC. |
ip | string | Source IP address of the attacker. |
method | string | HTTP method of the request (GET, POST, etc.). |
path | string | Request path that triggered the detection. |
threat_types | []string | List of detected threat types (e.g., SQLInjection, XSS). |
severity | string | Severity level: Low, Medium, High, or Critical. |
confidence | int | Detection confidence score (0-100). |
blocked | bool | Whether the request was blocked by the WAF. |
country | string | Country of origin (empty if geolocation is not enabled). |
evidence | string | The matched pattern or payload snippet that triggered the detection. |
Response Handling
Multiple Providers
You can configure all three providers simultaneously. When a qualifying threat event occurs, the dispatcher sends alerts to every configured provider concurrently. A failure in one provider does not prevent the others from receiving the alert.
1sentinel.Mount(r, nil, sentinel.Config{2 WAF: sentinel.WAFConfig{3 Enabled: true,4 Mode: sentinel.ModeBlock,5 },6 Alerts: sentinel.AlertConfig{7 MinSeverity: sentinel.SeverityHigh,89 // Slack for real-time team notifications10 Slack: &sentinel.SlackConfig{11 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxxx",12 },1314 // Email for the security team15 Email: &sentinel.EmailConfig{16 SMTPHost: "smtp.gmail.com",17 SMTPPort: 587,18 Username: "alerts@yourcompany.com",19 Password: "your-app-specific-password",20 Recipients: []string{"security-team@yourcompany.com"},21 },2223 // Webhook for SIEM integration24 Webhook: &sentinel.WebhookConfig{25 URL: "https://your-siem.example.com/api/v1/events",26 Headers: map[string]string{27 "Authorization": "Bearer your-siem-token",28 },29 },30 },31})
Independent Delivery
Alert History
Every alert dispatch attempt is recorded in an in-memory history log. Each entry tracks whether the alert was sent successfully or failed, along with the channel, severity, IP, threat type, and any error message.
AlertHistory Fields
| Field | Type | Description |
|---|---|---|
ID | string | Unique identifier for the history entry. |
Timestamp | time.Time | When the alert was dispatched. |
ThreatID | string | The ID of the threat event that triggered the alert. |
Channel | string | The provider channel: slack, email, or webhook. |
Severity | Severity | Severity of the threat event. |
IP | string | Source IP of the attacker. |
ThreatType | string | The primary threat type that triggered the alert. |
Success | bool | Whether the alert was delivered successfully. |
Error | string | Error message if the alert failed (empty on success). |
The history buffer retains the last 1,000 entries in memory. Older entries are evicted when new ones arrive. The history resets on application restart.
Dashboard
The Sentinel dashboard includes a dedicated Alerts page that provides visibility into your alerting configuration and delivery history.
- Configuration overview — see which providers are active, the current severity threshold, and the connection details for each provider.
- Alert history — browse the chronological log of all dispatched alerts with their delivery status, channel, severity, source IP, and threat type.
- Failure tracking — quickly identify failed deliveries and their error messages to diagnose connectivity or configuration issues.
Access the Alerts page at http://localhost:8080/sentinel/ui and navigate to the Alerts section.
Full Configuration Example
The following example enables the WAF in block mode with Slack alerting for high-severity events and a webhook for SIEM integration at medium severity:
1package main23import (4 sentinel "github.com/MUKE-coder/sentinel"5 "github.com/gin-gonic/gin"6)78func main() {9 r := gin.Default()1011 sentinel.Mount(r, nil, sentinel.Config{12 WAF: sentinel.WAFConfig{13 Enabled: true,14 Mode: sentinel.ModeBlock,15 },1617 Alerts: sentinel.AlertConfig{18 MinSeverity: sentinel.SeverityHigh,1920 Slack: &sentinel.SlackConfig{21 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxxx",22 },2324 Email: &sentinel.EmailConfig{25 SMTPHost: "smtp.gmail.com",26 SMTPPort: 587,27 Username: "alerts@yourcompany.com",28 Password: "your-app-specific-password",29 Recipients: []string{30 "security-team@yourcompany.com",31 },32 },3334 Webhook: &sentinel.WebhookConfig{35 URL: "https://your-siem.example.com/api/v1/events",36 Headers: map[string]string{37 "Authorization": "Bearer your-siem-token",38 },39 },40 },41 })4243 r.GET("/api/data", func(c *gin.Context) {44 c.JSON(200, gin.H{"status": "ok"})45 })4647 r.Run(":8080")48}
Next Steps
- WAF — Configure the detection rules that generate threat events
- Auth Shield — Protect login endpoints and generate auth-related alerts
- Anomaly Detection — Add behavioral analysis that feeds into alerting
- Threat Intelligence — Profile attackers and enrich alert data with geolocation
- Dashboard — View alert history and configuration in the UI