Security Score
The Security Score is a weighted composite metric (0-100) that measures your application's overall security posture at a glance. It aggregates five dimensions of your Sentinel configuration and runtime behavior into a single number, graded from A (90-100) to F (below 60). The score updates automatically in the background and surfaces actionable recommendations to improve your defenses.
Always Active
Config you pass to sentinel.Mount to evaluate which features are active and how well they are configured.Score Dimensions
The overall score is a weighted sum of five sub-scores. Each dimension evaluates a different aspect of your security posture:
| Dimension | Weight | What It Measures |
|---|---|---|
| Threat Activity | 30% | How many threats were detected in the last 24 hours and how severe they are. Fewer and lower-severity threats yield a higher score. A bonus is applied when your block rate exceeds 90%. |
| Auth Security | 20% | Whether you have changed the default dashboard password and secret key, and whether Auth Shield is enabled. Using defaults penalizes this sub-score. |
| Response Posture | 20% | The ratio of blocked threats to total threats. A 100% block rate yields a perfect sub-score. If the WAF is in log-only mode, unblocked threats lower this dimension. |
| Header Compliance | 15% | How many recommended security headers are configured: X-Frame-Options, Referrer-Policy, Content-Security-Policy, and Strict-Transport-Security. X-Content-Type-Options is always set by default. |
| Rate Limiting | 15% | Whether rate limiting is enabled and how comprehensively it is configured: per-IP, per-user, and per-route limits each contribute to this sub-score. |
How It's Computed
Sentinel launches a background goroutine when Mount is called. The ScoreEngine computes the score immediately on startup and then recomputes it every 5 minutes. Each cycle performs the following steps:
- Query threat stats — The engine calls
GetThreatStatson the storage layer with a 24-hour window to retrieve counts by severity and block status. - Evaluate each dimension — Five dedicated functions compute a sub-score (0-100) for each dimension using the threat stats and the current
Config. - Weighted aggregation — Sub-scores are multiplied by their weights and summed to produce the overall score.
- Grade assignment — The overall score is mapped to a letter grade.
- Recommendation generation — The engine inspects each sub-score and the config to produce actionable recommendations for any weak areas.
- Persist — The result is saved to storage via
SaveSecurityScoreso the dashboard and API can read it without recomputing.
1// ComputeScore calculates the security score based on current state.2func (e *ScoreEngine) ComputeScore(ctx context.Context) (*sentinel.SecurityScore, error) {3 stats, err := e.store.GetThreatStats(ctx, 24*time.Hour)4 if err != nil {5 return nil, err6 }78 threatScore := computeThreatActivityScore(stats) // weight: 30%9 authScore := computeAuthSecurityScore(e.config) // weight: 20%10 responseScore := computeResponsePostureScore(stats) // weight: 20%11 headerScore := computeHeaderComplianceScore(e.config) // weight: 15%12 rateLimitScore := computeRateLimitCoverageScore(e.config) // weight: 15%1314 overall := int(15 float64(threatScore)*0.30 +16 float64(authScore)*0.20 +17 float64(responseScore)*0.20 +18 float64(headerScore)*0.15 +19 float64(rateLimitScore)*0.15,20 )2122 grade := scoreToGrade(overall)23 recommendations := generateRecommendations(24 threatScore, authScore, responseScore,25 headerScore, rateLimitScore, e.config,26 )2728 score := &sentinel.SecurityScore{29 Overall: overall,30 Grade: grade,31 // ... sub-scores, computed_at, recommendations32 }3334 e.store.SaveSecurityScore(ctx, score)35 return score, nil36}
Grading Scale
| Score Range | Grade | Interpretation |
|---|---|---|
| 90 - 100 | A | Excellent. All major features enabled and well-configured. |
| 80 - 89 | B | Good. Minor improvements available. |
| 70 - 79 | C | Fair. Some important features are missing or misconfigured. |
| 60 - 69 | D | Poor. Significant gaps in your security posture. |
| 0 - 59 | F | Failing. Critical features are disabled or defaults are unchanged. |
Sub-Score Details
Threat Activity (30%)
Starts at 100 and deducts points for each threat detected in the last 24 hours. Deductions scale by severity: critical threats cost 20 points each, high costs 10, medium costs 5, and low costs 2. A bonus of +10 is applied when over 90% of threats are blocked, or +5 when over 50% are blocked. With no threats in the window, the sub-score is a perfect 100.
Auth Security (20%)
Starts at a base of 50. Changing the default dashboard password from "sentinel" adds 20 points. Changing the default secret key adds another 20. Enabling Auth Shield adds 10. A fully configured authentication setup scores 100.
Response Posture (20%)
Measures the percentage of threats that were actively blocked. If all detected threats are blocked (WAF in block mode), the sub-score is 100. If no threats have been detected, the baseline score is 80. Running the WAF in log-only mode typically lowers this dimension because threats are recorded but not blocked.
Header Compliance (15%)
Counts how many of the five recommended security headers are configured: X-Content-Type-Options (always on), X-Frame-Options, Referrer-Policy, Content-Security-Policy, and Strict-Transport-Security. Each configured header contributes equally. If security headers are explicitly disabled, the sub-score is 0.
Rate Limiting (15%)
Awards a base of 30 points for having rate limiting enabled. Additional points come from configuring per-IP limits (+30), per-user limits (+20), and per-route limits (+20). Disabling rate limiting entirely results in a sub-score of 0.
Maximizing Your Score
Recommendations
After computing the score, the engine generates a list of actionable recommendations based on which features are disabled or which sub-scores fall below their thresholds. Each recommendation includes a title, description, impact level, and the category it addresses.
| Condition | Recommendation | Impact | Category |
|---|---|---|---|
| WAF disabled | Enable WAF to protect against common attacks | High | threat_activity |
| WAF in log-only mode | Set WAF to block mode to actively prevent attacks | High | response_posture |
| Rate limiting disabled | Enable rate limiting to prevent abuse and brute force | Medium | rate_limit_coverage |
| Header compliance below 80 | Configure CSP and HSTS headers | Medium | header_compliance |
| Auth security below 70 | Change default passwords and enable Auth Shield | High | auth_security |
// Example recommendation structuretype Recommendation struct {Title string `json:"title"`Description string `json:"description"`Impact string `json:"impact"` // "High", "Medium", "Low"Category string `json:"category"` // matches a sub-score dimension}
Act on Recommendations
API
The security score is available through a single authenticated endpoint. The response includes the overall score, grade, each sub-score with its weight and label, the computation timestamp, trend direction, and the list of recommendations.
Get Security Score
| Property | Value |
|---|---|
| Endpoint | GET /sentinel/api/score |
| Auth | JWT token in Authorization: Bearer <token> |
curl -s -H "Authorization: Bearer <token>" \"http://localhost:8080/sentinel/api/score" | jq .
{"data": {"overall": 82,"grade": "B","threat_activity": {"score": 90,"weight": 0.3,"label": "Threat Activity"},"auth_security": {"score": 80,"weight": 0.2,"label": "Auth Security"},"response_posture": {"score": 100,"weight": 0.2,"label": "Response Posture"},"header_compliance": {"score": 60,"weight": 0.15,"label": "Header Compliance"},"rate_limit_coverage": {"score": 50,"weight": 0.15,"label": "Rate Limiting"},"computed_at": "2025-01-15T14:30:00Z","trend": "stable","recommendations": [{"title": "Add Security Headers","description": "Configure Content-Security-Policy and Strict-Transport-Security headers.","impact": "Medium","category": "header_compliance"},{"title": "Enable Rate Limiting","description": "Enable rate limiting to prevent abuse and brute force attacks.","impact": "Medium","category": "rate_limit_coverage"}]}}
Dashboard
The security score is surfaced in two places within the Sentinel dashboard:
- Main Dashboard — The home page displays the overall score as a ring gauge with the letter grade at the center. The gauge color shifts from red (F) through amber (C/D) to green (A/B), providing an instant visual indicator of your security posture.
- Analytics Page — The analytics section shows a detailed score breakdown with each sub-score displayed individually. This view lets you identify which specific dimension is dragging down your overall score and view the associated recommendations.
Access the dashboard at http://localhost:8080/sentinel/ui after mounting Sentinel.
Configuration
The score engine does not have its own configuration block. It reads the main Config you pass to sentinel.Mount to determine which features are enabled and how they are configured. The sub-scores react directly to your config:
| Config Area | Affects Dimension | What the Engine Checks |
|---|---|---|
WAF | Threat Activity, Response Posture | Whether WAF is enabled and whether it is in block or log mode. |
RateLimit | Rate Limiting | Whether rate limiting is enabled and which limit types are configured (by-IP, by-user, by-route). |
Headers | Header Compliance | Which security headers are explicitly set in the config. |
Dashboard | Auth Security | Whether the password and secret key have been changed from their defaults. |
AuthShield | Auth Security | Whether Auth Shield brute-force protection is enabled. |
1package main23import (4 "time"56 sentinel "github.com/MUKE-coder/sentinel"7 "github.com/gin-gonic/gin"8)910func main() {11 r := gin.Default()1213 // A well-configured setup that achieves a high security score14 sentinel.Mount(r, nil, sentinel.Config{15 // WAF in block mode -> high Threat Activity & Response Posture16 WAF: sentinel.WAFConfig{17 Enabled: true,18 Mode: sentinel.ModeBlock,19 },2021 // Rate limiting with per-IP and per-user -> high Rate Limiting22 RateLimit: sentinel.RateLimitConfig{23 Enabled: true,24 ByIP: &sentinel.Limit{Requests: 100, Window: time.Minute},25 ByUser: &sentinel.Limit{Requests: 200, Window: time.Minute},26 ByRoute: map[string]sentinel.Limit{27 "/api/login": {Requests: 5, Window: 15 * time.Minute},28 },29 },3031 // Full security headers -> high Header Compliance32 Headers: sentinel.HeadersConfig{33 XFrameOptions: "DENY",34 ReferrerPolicy: "strict-origin-when-cross-origin",35 ContentSecurityPolicy: "default-src 'self'",36 StrictTransportSecurity: true,37 },3839 // Custom credentials -> high Auth Security40 Dashboard: sentinel.DashboardConfig{41 Password: "my-strong-password",42 SecretKey: "my-custom-jwt-secret-key",43 },4445 // Auth Shield enabled -> bonus Auth Security points46 AuthShield: sentinel.AuthShieldConfig{47 Enabled: true,48 MaxAttempts: 5,49 LockoutDuration: 15 * time.Minute,50 },51 })5253 r.GET("/api/data", func(c *gin.Context) {54 c.JSON(200, gin.H{"status": "ok"})55 })5657 r.Run(":8080")58}
Background Recomputation
GET /sentinel/api/score triggers a fresh computation on each request, so you always get the latest result. The background goroutine ensures the persisted score stays current for the dashboard even when the API is not being called.Next Steps
- Configuration Reference — Full config field reference for all features that affect the score
- WAF — Enable and configure the WAF to improve Threat Activity and Response Posture
- Rate Limiting — Configure rate limits to boost the Rate Limiting dimension
- Security Headers — Add headers to maximize Header Compliance
- Auth Shield — Enable brute-force protection to raise Auth Security