143 lines
3.7 KiB
Go
143 lines
3.7 KiB
Go
package services
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/Wikid82/charon/backend/internal/models"
|
|
)
|
|
|
|
// ScoreBreakdown represents the detailed score calculation
|
|
type ScoreBreakdown struct {
|
|
TotalScore int `json:"score"`
|
|
MaxScore int `json:"max_score"`
|
|
Breakdown map[string]int `json:"breakdown"`
|
|
Suggestions []string `json:"suggestions"`
|
|
}
|
|
|
|
// CalculateSecurityScore calculates the security score for a profile
|
|
func CalculateSecurityScore(profile *models.SecurityHeaderProfile) ScoreBreakdown {
|
|
breakdown := make(map[string]int)
|
|
suggestions := []string{}
|
|
maxScore := 100
|
|
|
|
// HSTS (25 points max)
|
|
hstsScore := 0
|
|
if profile.HSTSEnabled {
|
|
hstsScore += 10
|
|
if profile.HSTSMaxAge >= 31536000 {
|
|
hstsScore += 5
|
|
} else {
|
|
suggestions = append(suggestions, "Increase HSTS max-age to at least 1 year")
|
|
}
|
|
if profile.HSTSIncludeSubdomains {
|
|
hstsScore += 5
|
|
} else {
|
|
suggestions = append(suggestions, "Enable HSTS for subdomains")
|
|
}
|
|
if profile.HSTSPreload {
|
|
hstsScore += 5
|
|
} else {
|
|
suggestions = append(suggestions, "Consider HSTS preload for browser preload lists")
|
|
}
|
|
} else {
|
|
suggestions = append(suggestions, "Enable HSTS to enforce HTTPS")
|
|
}
|
|
breakdown["hsts"] = hstsScore
|
|
|
|
// CSP (25 points max)
|
|
cspScore := 0
|
|
if profile.CSPEnabled {
|
|
cspScore += 15
|
|
// Additional points for strict CSP
|
|
if !strings.Contains(profile.CSPDirectives, "'unsafe-inline'") {
|
|
cspScore += 5
|
|
} else {
|
|
suggestions = append(suggestions, "Avoid 'unsafe-inline' in CSP for better security")
|
|
}
|
|
if !strings.Contains(profile.CSPDirectives, "'unsafe-eval'") {
|
|
cspScore += 5
|
|
} else {
|
|
suggestions = append(suggestions, "Avoid 'unsafe-eval' in CSP for better security")
|
|
}
|
|
} else {
|
|
suggestions = append(suggestions, "Enable Content-Security-Policy")
|
|
}
|
|
breakdown["csp"] = cspScore
|
|
|
|
// X-Frame-Options (10 points)
|
|
xfoScore := 0
|
|
switch profile.XFrameOptions {
|
|
case "DENY":
|
|
xfoScore = 10
|
|
case "SAMEORIGIN":
|
|
xfoScore = 7
|
|
default:
|
|
suggestions = append(suggestions, "Set X-Frame-Options to DENY or SAMEORIGIN")
|
|
}
|
|
breakdown["x_frame_options"] = xfoScore
|
|
|
|
// X-Content-Type-Options (10 points)
|
|
xctoScore := 0
|
|
if profile.XContentTypeOptions {
|
|
xctoScore = 10
|
|
} else {
|
|
suggestions = append(suggestions, "Enable X-Content-Type-Options: nosniff")
|
|
}
|
|
breakdown["x_content_type_options"] = xctoScore
|
|
|
|
// Referrer-Policy (10 points)
|
|
rpScore := 0
|
|
strictPolicies := []string{"no-referrer", "strict-origin", "strict-origin-when-cross-origin"}
|
|
for _, p := range strictPolicies {
|
|
if profile.ReferrerPolicy == p {
|
|
rpScore = 10
|
|
break
|
|
}
|
|
}
|
|
if profile.ReferrerPolicy == "origin-when-cross-origin" {
|
|
rpScore = 7
|
|
}
|
|
if rpScore == 0 && profile.ReferrerPolicy != "" {
|
|
rpScore = 3
|
|
}
|
|
if rpScore < 10 {
|
|
suggestions = append(suggestions, "Use a stricter Referrer-Policy")
|
|
}
|
|
breakdown["referrer_policy"] = rpScore
|
|
|
|
// Permissions-Policy (10 points)
|
|
ppScore := 0
|
|
if profile.PermissionsPolicy != "" {
|
|
ppScore = 10
|
|
} else {
|
|
suggestions = append(suggestions, "Add Permissions-Policy to restrict browser features")
|
|
}
|
|
breakdown["permissions_policy"] = ppScore
|
|
|
|
// Cross-Origin headers (10 points)
|
|
coScore := 0
|
|
if profile.CrossOriginOpenerPolicy != "" {
|
|
coScore += 4
|
|
}
|
|
if profile.CrossOriginResourcePolicy != "" {
|
|
coScore += 3
|
|
}
|
|
if profile.CrossOriginEmbedderPolicy != "" {
|
|
coScore += 3
|
|
}
|
|
if coScore < 10 {
|
|
suggestions = append(suggestions, "Add Cross-Origin isolation headers")
|
|
}
|
|
breakdown["cross_origin"] = coScore
|
|
|
|
// Calculate total
|
|
total := hstsScore + cspScore + xfoScore + xctoScore + rpScore + ppScore + coScore
|
|
|
|
return ScoreBreakdown{
|
|
TotalScore: total,
|
|
MaxScore: maxScore,
|
|
Breakdown: breakdown,
|
|
Suggestions: suggestions,
|
|
}
|
|
}
|