Sistema de Scoring MSSS v2.0¶
Documento tecnico para analistas de seguridad
1. Introduccion¶
MSSS (MCP Server Security Standard) es el sistema de scoring utilizado por mcp-scan para evaluar la postura de seguridad de un servidor MCP. El score va de 0 a 100, donde 100 representa un servidor sin hallazgos de seguridad.
Novedades en v2.0¶
La version 2.0 introduce un modelo hibrido multiplicativo que resuelve el problema de scores enganosos:
| Escenario | Score v1.0 | Score v2.0 |
|---|---|---|
| 2 findings HIGH | ~93 (Level 1) | ~49 (Level 0) |
| 1 CRITICAL | ~90 | ~37 |
Cambios principales: - Eliminados limites por categoria - Penalizaciones aumentadas (CRITICAL: 25, HIGH: 15, MEDIUM: 5) - Multiplicador de severidad para efecto compuesto - Score alineado con expectativas de Level
2. Arquitectura del Sistema¶
2.1 Componentes¶
+------------------+
| Findings | <-- Lista de hallazgos
+------------------+
|
v
+------------------+
| Calculator | <-- internal/msss/msss.go
+------------------+
|
+---> Direct Penalties (sin limite)
+---> Severity Multiplier (compuesto)
|
v
+------------------+
| Score |
| - Total (0-100) |
| - Level (0-3) |
| - Categories |
| - Details |
+------------------+
2.2 Estructura del Score¶
type Score struct {
Total float64 `json:"total"` // 0-100
Categories map[string]CategoryScore `json:"categories"` // Por clase
Version string `json:"version"` // "2.0"
Compliant bool `json:"compliant"` // >= Level 1
Level int `json:"level"` // 0-3
Details *ScoreDetails `json:"details"` // Desglose
}
type CategoryScore struct {
Score float64 `json:"score"` // Score actual
MaxScore float64 `json:"max_score"` // Maximo posible
Weight float64 `json:"weight"` // Peso en total
Findings int `json:"findings"` // Numero de hallazgos
Penalties float64 `json:"penalties"` // Penalizaciones
}
type ScoreDetails struct {
BaseScore float64 `json:"base_score"` // Siempre 100
Penalties float64 `json:"penalties"` // Total penalizaciones
SeverityMultiplier float64 `json:"severity_multiplier"` // Multiplicador compuesto
CriticalCount int `json:"critical_count"` // Conteo de criticals
HighCount int `json:"high_count"` // Conteo de highs
Bonuses float64 `json:"bonuses"` // Bonificaciones
FindingsPenalty map[string]float64 `json:"findings_penalty"` // Por finding
}
3. Formula de Scoring v2.0¶
3.1 Formula Principal¶
3.2 Pasos del Calculo¶
- Sumar penalizaciones directas (sin limite por categoria)
- Calcular multiplicador de severidad (efecto compuesto)
- Aplicar formula
4. Penalizaciones Directas¶
4.1 Penalizacion Base por Severidad (v2.0)¶
| Severidad | Penalizacion Base | Cambio vs v1.0 |
|---|---|---|
| Critical | 25.0 | +150% (era 10.0) |
| High | 15.0 | +200% (era 5.0) |
| Medium | 5.0 | +150% (era 2.0) |
| Low | 1.0 | +100% (era 0.5) |
| Info | 0.2 | +100% (era 0.1) |
4.2 Multiplicador de Confianza¶
| Confianza | Multiplicador |
|---|---|
| High | 1.0 (100%) |
| Medium | 0.7 (70%) |
| Low | 0.4 (40%) |
4.3 Multiplicador MCP Context¶
| Contexto | Multiplicador |
|---|---|
| En tool handler | 1.3 (+30%) |
| Fuera de tool | 1.0 |
4.4 Formula de Penalizacion Individual¶
Penalizacion = Base_Severidad × Factor_Confianza × Factor_MCP
Donde:
- Base_Severidad: {Critical: 25, High: 15, Medium: 5, Low: 1, Info: 0.2}
- Factor_Confianza: {High: 1.0, Medium: 0.7, Low: 0.4}
- Factor_MCP: {En tool: 1.3, Fuera: 1.0}
4.5 Codigo¶
func (c *Calculator) calculatePenalty(f types.Finding) float64 {
var base float64
switch f.Severity {
case types.SeverityCritical:
base = 25.0 // Era 10.0
case types.SeverityHigh:
base = 15.0 // Era 5.0
case types.SeverityMedium:
base = 5.0 // Era 2.0
case types.SeverityLow:
base = 1.0 // Era 0.5
case types.SeverityInfo:
base = 0.2 // Era 0.1
}
// Multiplicador de confianza
var confMult float64
switch f.Confidence {
case types.ConfidenceHigh:
confMult = 1.0
case types.ConfidenceMedium:
confMult = 0.7
case types.ConfidenceLow:
confMult = 0.4
}
// Multiplicador MCP
mcpMult := 1.0
if f.MCPContext != nil {
mcpMult = 1.3
}
return base * confMult * mcpMult
}
5. Multiplicador de Severidad¶
5.1 Concepto¶
El multiplicador de severidad proporciona un efecto compuesto para multiples hallazgos HIGH/CRITICAL. Esto asegura que 2 HIGHs tengan un impacto mucho mayor que 1 HIGH.
5.2 Valores del Multiplicador¶
Para CRITICAL findings:
| Criticals | Multiplicador | Formula |
|---|---|---|
| 1 | 0.50 | 0.50 - 0×0.15 |
| 2 | 0.35 | 0.50 - 1×0.15 |
| 3+ | 0.25 | min(0.25) |
Para HIGH findings (si no hay CRITICAL):
| Highs | Multiplicador | Formula |
|---|---|---|
| 1 | 0.85 | 1.0 - 1×0.15 |
| 2 | 0.70 | 1.0 - 2×0.15 |
| 3 | 0.55 | 1.0 - 3×0.15 |
| 4+ | 0.45 | min(0.45) |
Sin HIGH/CRITICAL: multiplicador = 1.0
5.3 Codigo¶
func (c *Calculator) calculateSeverityMultiplier(criticalCount, highCount int) float64 {
if criticalCount >= 1 {
// Critical: 0.50, 0.35, 0.25 (min)
return math.Max(0.25, 0.50-float64(criticalCount-1)*0.15)
}
if highCount >= 1 {
// High: 0.85, 0.70, 0.55, 0.45 (min)
return math.Max(0.45, 1.0-float64(highCount)*0.15)
}
return 1.0
}
6. Niveles de Certificacion¶
6.1 Tabla de Niveles¶
| Nivel | Nombre | Requisitos | Target |
|---|---|---|---|
| 0 | No Certified | < 60 OR criticals > 0 OR highs > 3 | - |
| 1 | Basic | >= 60, 0 critical, <= 3 high | OSS |
| 2 | Secure | >= 80, 0 high, 0 critical | PRO |
| 3 | Certified | >= 90, 0 high, 0 critical | Enterprise |
6.2 Algoritmo de Nivel¶
func (c *Calculator) determineLevel(total float64, findings []types.Finding) int {
criticalCount := countBySeverity(findings, types.SeverityCritical)
highCount := countBySeverity(findings, types.SeverityHigh)
// Level 0: cualquier critical, score < 60, o > 3 high
if criticalCount > 0 || total < 60 || highCount > 3 {
return 0
}
// Level 2/3: requiere 0 high
if highCount == 0 {
if total >= 90 {
return 3
}
if total >= 80 {
return 2
}
}
// Level 1: >= 60, no critical, 1-3 high
return 1
}
6.3 Diagrama de Decision¶
+----------------+
| criticals > 0? |
+----------------+
|yes |no
v v
Level 0 +----------------+
| score < 60? |
+----------------+
|yes |no
v v
Level 0 +----------------+
| highs > 3? |
+----------------+
|yes |no
v v
Level 0 +----------------+
| highs == 0? |
+----------------+
|no |yes
v v
Level 1 +----------------+
| score >= 90? |
+----------------+
|no |yes
v v
Level 2 Level 3
7. Ejemplos de Calculo¶
7.1 Ejemplo 1: Servidor Limpio¶
Findings: Ninguno
7.2 Ejemplo 2: Un HIGH Finding¶
Findings: 1 HIGH, High confidence
Penalizacion = 15.0 × 1.0 × 1.0 = 15.0
Multiplicador = 0.85 (1 high)
Score = (100 - 15) × 0.85 = 72.25
Level = 1 (>= 60, 1 high <= 3)
7.3 Ejemplo 3: Dos HIGH Findings¶
Findings: 2 HIGH, High confidence
Penalizaciones = 15.0 + 15.0 = 30.0
Multiplicador = 0.70 (2 high)
Score = (100 - 30) × 0.70 = 49.0
Level = 0 (score < 60)
7.4 Ejemplo 4: Un CRITICAL Finding¶
Findings: 1 CRITICAL, High confidence
Penalizacion = 25.0 × 1.0 × 1.0 = 25.0
Multiplicador = 0.50 (1 critical)
Score = (100 - 25) × 0.50 = 37.5
Level = 0 (critical presente)
7.5 Ejemplo 5: Cinco MEDIUM Findings¶
Findings: 5 MEDIUM, High confidence
Penalizaciones = 5.0 × 5 = 25.0
Multiplicador = 1.0 (no high/critical)
Score = (100 - 25) × 1.0 = 75.0
Level = 1 (>= 60, < 80, no high)
7.6 Ejemplo 6: Mixto (2 HIGH + 3 MEDIUM)¶
Findings: 2 HIGH + 3 MEDIUM, High confidence
Penalizaciones = (15.0 × 2) + (5.0 × 3) = 45.0
Multiplicador = 0.70 (2 high)
Score = (100 - 45) × 0.70 = 38.5
Level = 0 (score < 60)
8. Pesos por Categoria¶
8.1 Tabla de Pesos¶
Los pesos suman 100% y reflejan el impacto relativo de cada clase:
| Clase | Nombre | Peso | Justificacion |
|---|---|---|---|
| A | RCE | 22.0% | Maximo impacto - compromiso total |
| B | Filesystem | 13.0% | Acceso a datos sensibles |
| C | SSRF | 10.0% | Puede escalar a RCE interno |
| D | SQLi | 10.0% | Compromiso de base de datos |
| E | Secrets | 10.0% | Credenciales comprometen todo |
| F | Auth | 8.0% | Bypass de autenticacion |
| G | Tool Poisoning | 8.0% | Especifico de MCP |
| H | Declaration Mismatch | 5.0% | Engano al usuario |
| I | Multi-Tool Flow | 4.0% | Requiere combinacion |
| J | Memory Injection | 3.0% | Impacto diferido |
| K | Task Queue | 3.0% | Impacto diferido |
| N | Supply Chain | 4.0% | Riesgo externo |
| Total | 100.0% |
9. Output del Score¶
9.1 JSON Output¶
{
"total": 49.0,
"level": 0,
"compliant": false,
"version": "2.0",
"categories": {
"A": {
"score": 7.0,
"max_score": 22.0,
"weight": 22.0,
"findings": 1,
"penalties": 15.0
},
"B": {
"score": 0.0,
"max_score": 13.0,
"weight": 13.0,
"findings": 1,
"penalties": 15.0
}
},
"details": {
"base_score": 100.0,
"penalties": 30.0,
"severity_multiplier": 0.70,
"critical_count": 0,
"high_count": 2,
"bonuses": 0,
"findings_penalty": {
"finding-1": 15.0,
"finding-2": 15.0
}
}
}
9.2 Uso en CLI¶
$ mcp-scan scan ./server.py
MSSS Score: 49.0 / 100
Level: 0 (Not Certified)
Score Breakdown:
Base Score: 100.0
Total Penalties: -30.0
Severity Multiplier: ×0.70 (2 HIGH findings)
Formula: (100 - 30) × 0.70 = 49.0
Category Breakdown:
A (RCE): 7.0 / 22.0 [1 finding, -15.0]
B (Filesystem): 0.0 / 13.0 [1 finding, -15.0]
C (SSRF): 10.0 / 10.0 [0 findings]
...
Findings:
[HIGH] MCP-A001: Tool input flows to command execution
Location: server.py:15
Penalty: -15.0
[HIGH] MCP-B001: Path traversal in file read
Location: server.py:42
Penalty: -15.0
10. Comparacion v1.0 vs v2.0¶
| Aspecto | v1.0 | v2.0 |
|---|---|---|
| Formula | Suma por categorias | Hibrido multiplicativo |
| Limites por categoria | Si | No |
| Penalizacion HIGH | 5.0 | 15.0 |
| Penalizacion CRITICAL | 10.0 | 25.0 |
| Efecto compuesto | Debil (0.1/critical) | Fuerte (multiplicador) |
| 2 HIGH findings | ~93 (enganoso) | ~49 (preciso) |
| Alineacion score-level | Pobre | Fuerte |
11. Interpretacion para Analistas¶
11.1 Score Alto (90-100)¶
- Servidor muy seguro
- Solo hallazgos informativos o low
- Candidato a Level 3
- Accion: Mantenimiento
11.2 Score Medio-Alto (70-89)¶
- Buena postura de seguridad
- Maximo 1 HIGH
- Candidato a Level 1-2
- Accion: Remediar HIGH para Level 2+
11.3 Score Medio (50-69)¶
- Problemas de seguridad moderados
- 1-2 HIGH o varios MEDIUM
- Level 1 o 0
- Accion: Priorizar remediacion
11.4 Score Bajo (< 50)¶
- Problemas serios de seguridad
- 2+ HIGH o CRITICAL presente
- Level 0
- Accion: Atencion urgente
11.5 Prioridad de Remediacion¶
- Primero: Eliminar CRITICAL (multiplicador 0.50)
- Segundo: Reducir HIGH a <= 1 (multiplicador 0.85)
- Tercero: Abordar MEDIUM en categorias de alto peso
- Ultimo: LOW e informativos
12. Helpers del Calculator¶
12.1 GetCriticalClasses¶
Obtiene las clases con hallazgos criticos:
12.2 GetTopFindings¶
Obtiene los N hallazgos mas severos:
13. Limitaciones¶
13.1 Limitaciones del Scoring¶
- No considera contexto de negocio: Un SQLi en datos publicos vs privados tiene mismo peso
- Pesos fijos: No se ajustan por tipo de aplicacion
- No considera mitigaciones externas: Un hallazgo con WAF cuenta igual
- Multiplicador simplificado: No distingue entre tipos de HIGH
13.2 Recomendaciones¶
- Usar como guia, no como unica metrica
- Revisar hallazgos HIGH/CRITICAL manualmente
- Considerar contexto del servidor MCP
- Trackear mejora con scans regulares
Siguiente documento: superficie-mcp.md