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

The score engine runs automatically once Sentinel is mounted. There is no separate configuration to enable it. It uses the main 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:

DimensionWeightWhat It Measures
Threat Activity30%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 Security20%Whether you have changed the default dashboard password and secret key, and whether Auth Shield is enabled. Using defaults penalizes this sub-score.
Response Posture20%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 Compliance15%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 Limiting15%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:

  1. Query threat stats — The engine calls GetThreatStats on the storage layer with a 24-hour window to retrieve counts by severity and block status.
  2. Evaluate each dimension — Five dedicated functions compute a sub-score (0-100) for each dimension using the threat stats and the current Config.
  3. Weighted aggregation — Sub-scores are multiplied by their weights and summed to produce the overall score.
  4. Grade assignment — The overall score is mapped to a letter grade.
  5. Recommendation generation — The engine inspects each sub-score and the config to produce actionable recommendations for any weak areas.
  6. Persist — The result is saved to storage via SaveSecurityScore so the dashboard and API can read it without recomputing.
intelligence/security_score.gogo
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, err
6 }
7
8 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%
13
14 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 )
21
22 grade := scoreToGrade(overall)
23 recommendations := generateRecommendations(
24 threatScore, authScore, responseScore,
25 headerScore, rateLimitScore, e.config,
26 )
27
28 score := &sentinel.SecurityScore{
29 Overall: overall,
30 Grade: grade,
31 // ... sub-scores, computed_at, recommendations
32 }
33
34 e.store.SaveSecurityScore(ctx, score)
35 return score, nil
36}

Grading Scale

Score RangeGradeInterpretation
90 - 100AExcellent. All major features enabled and well-configured.
80 - 89BGood. Minor improvements available.
70 - 79CFair. Some important features are missing or misconfigured.
60 - 69DPoor. Significant gaps in your security posture.
0 - 59FFailing. 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

To reach an A grade: enable WAF in block mode, enable rate limiting with per-IP and per-user limits, configure all five security headers, change the default dashboard password and secret key, and enable Auth Shield. These settings cover all five dimensions.

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.

ConditionRecommendationImpactCategory
WAF disabledEnable WAF to protect against common attacksHighthreat_activity
WAF in log-only modeSet WAF to block mode to actively prevent attacksHighresponse_posture
Rate limiting disabledEnable rate limiting to prevent abuse and brute forceMediumrate_limit_coverage
Header compliance below 80Configure CSP and HSTS headersMediumheader_compliance
Auth security below 70Change default passwords and enable Auth ShieldHighauth_security
intelligence/security_score.gogo
// Example recommendation structure
type 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

Recommendations are not just informational. Each one directly maps to a sub-score dimension. Implementing a high-impact recommendation can raise your overall score by 10-20 points.

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

PropertyValue
EndpointGET /sentinel/api/score
AuthJWT token in Authorization: Bearer <token>
curl -s -H "Authorization: Bearer <token>" \
"http://localhost:8080/sentinel/api/score" | jq .
Responsejson
{
"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 AreaAffects DimensionWhat the Engine Checks
WAFThreat Activity, Response PostureWhether WAF is enabled and whether it is in block or log mode.
RateLimitRate LimitingWhether rate limiting is enabled and which limit types are configured (by-IP, by-user, by-route).
HeadersHeader ComplianceWhich security headers are explicitly set in the config.
DashboardAuth SecurityWhether the password and secret key have been changed from their defaults.
AuthShieldAuth SecurityWhether Auth Shield brute-force protection is enabled.
main.gogo
1package main
2
3import (
4 "time"
5
6 sentinel "github.com/MUKE-coder/sentinel"
7 "github.com/gin-gonic/gin"
8)
9
10func main() {
11 r := gin.Default()
12
13 // A well-configured setup that achieves a high security score
14 sentinel.Mount(r, nil, sentinel.Config{
15 // WAF in block mode -> high Threat Activity & Response Posture
16 WAF: sentinel.WAFConfig{
17 Enabled: true,
18 Mode: sentinel.ModeBlock,
19 },
20
21 // Rate limiting with per-IP and per-user -> high Rate Limiting
22 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 },
30
31 // Full security headers -> high Header Compliance
32 Headers: sentinel.HeadersConfig{
33 XFrameOptions: "DENY",
34 ReferrerPolicy: "strict-origin-when-cross-origin",
35 ContentSecurityPolicy: "default-src 'self'",
36 StrictTransportSecurity: true,
37 },
38
39 // Custom credentials -> high Auth Security
40 Dashboard: sentinel.DashboardConfig{
41 Password: "my-strong-password",
42 SecretKey: "my-custom-jwt-secret-key",
43 },
44
45 // Auth Shield enabled -> bonus Auth Security points
46 AuthShield: sentinel.AuthShieldConfig{
47 Enabled: true,
48 MaxAttempts: 5,
49 LockoutDuration: 15 * time.Minute,
50 },
51 })
52
53 r.GET("/api/data", func(c *gin.Context) {
54 c.JSON(200, gin.H{"status": "ok"})
55 })
56
57 r.Run(":8080")
58}

Background Recomputation

The score engine runs in a background goroutine that ticks every 5 minutes. It also computes the score once immediately on startup. The API endpoint 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

Built with by JB