scoring

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package scoring ports src/sec_af/scoring.py — the deterministic exploitability scoring engine: the severity/evidence/reachability weight tables, the CWE severity floors, and the score → label mapping.

Everything here is pure: no LLM, no I/O. The orchestrator calls ComputeExploitabilityScore for every VerifiedFinding in _generate_output and ApplyCWESeverityFloor before that.

Index

Constants

This section is empty.

Variables

View Source
var CWESeverityFloor = map[string]schemas.Severity{

	"CWE-78": schemas.SeverityCritical,
	"CWE-77": schemas.SeverityCritical,
	"CWE-94": schemas.SeverityCritical,
	"CWE-95": schemas.SeverityCritical,
	"CWE-96": schemas.SeverityCritical,

	"CWE-89": schemas.SeverityCritical,

	"CWE-502": schemas.SeverityCritical,

	"CWE-918": schemas.SeverityHigh,

	"CWE-287": schemas.SeverityHigh,
	"CWE-290": schemas.SeverityHigh,
	"CWE-306": schemas.SeverityHigh,

	"CWE-798": schemas.SeverityHigh,

	"CWE-22": schemas.SeverityHigh,

	"CWE-611": schemas.SeverityHigh,

	"CWE-79": schemas.SeverityMedium,

	"CWE-840": schemas.SeverityHigh,
	"CWE-862": schemas.SeverityHigh,
	"CWE-863": schemas.SeverityHigh,
}

CWESeverityFloor is the minimum severity for well-known vulnerability classes. LLMs consistently underrate injection and RCE, so this is a hard floor: CWE-78 can never be reported as "medium".

Ports scoring.py CWE_SEVERITY_FLOOR — byte-for-byte the same 18 entries.

EvidenceMultipliers scales the base weight by how strong the proof is.

Ports scoring.py EVIDENCE_MULTIPLIERS (declared there in decreasing order; the map has no order, the values are what matter).

View Source
var ReachabilityMultipliers = map[string]float64{
	"externally_reachable": 1.0,
	"internally_reachable": 0.7,
	"requires_auth":        0.5,
	"requires_admin":       0.3,
}

ReachabilityMultipliers scales the score by how exposed the code path is.

Ports scoring.py REACHABILITY_MULTIPLIERS.

SeverityWeights is the base weight per severity label.

Ports scoring.py SEVERITY_WEIGHTS. Keyed by the ENUM VALUE (Python indexes it with `finding.severity.value`), which is what schemas.Severity already is.

Functions

func ApplyCWESeverityFloor

func ApplyCWESeverityFloor(cweID string, current schemas.Severity) schemas.Severity

ApplyCWESeverityFloor upgrades a severity when the CWE has a known minimum floor, and otherwise returns it unchanged.

Ports scoring.py apply_cwe_severity_floor. Python parity: the comparison is `_SEVERITY_ORDER.get(label, 0) > _SEVERITY_ORDER.get(current.value, 0)`, so an UNKNOWN current severity ranks as 0 (info) and any floor beats it.

func AssignSeverityLabel

func AssignSeverityLabel(score float64) string

AssignSeverityLabel maps an exploitability score onto a severity label.

Ports scoring.py assign_severity_label. Boundaries are inclusive on the lower end: >=9 critical, >=7 high, >=4 medium, >=1 low, else info.

func ComputeExploitabilityScore

func ComputeExploitabilityScore(finding schemas.VerifiedFinding) float64

ComputeExploitabilityScore is the 0-10 exploitability score for a finding: severity weight × evidence multiplier × reachability multiplier × chain bonus, clamped to [0, 10] and rounded to 2 decimals.

Ports scoring.py compute_exploitability_score. The chain bonus is 2.0 when the finding belongs to an attack chain, else 1.0.

Python parity divergence (deliberate, documented): Python indexes SEVERITY_WEIGHTS / EVIDENCE_MULTIPLIERS directly, so an out-of-vocabulary severity or evidence level raises KeyError. Pydantic makes that unreachable in Python (both fields are enums), but Go's schemas.Severity is a string type that a hand-built struct could set to anything. Go treats an unknown key as weight 0.0 — the score collapses to 0.0 rather than panicking mid audit.

The final `round(..., 2)` goes through pyfmt.Round, which reproduces CPython's round-half-to-EVEN on the exact binary value — NOT math.Round(x*100)/100, which rounds half away from zero and accumulates the scaling error.

func ComputePriorityRank

func ComputePriorityRank(findings []schemas.VerifiedFinding) []schemas.VerifiedFinding

ComputePriorityRank returns the findings sorted by exploitability score, highest first, as a NEW slice (Python's `sorted()` copies; the input order is untouched).

Ports scoring.py compute_priority_rank. Python's sorted() is stable and `reverse=True` preserves the original order among equal keys, so Go uses sort.SliceStable — sort.Slice would be free to reorder ties and break tests/test_scoring.py::test_compute_priority_rank_is_stable_for_equal_scores. The score is computed ONCE per finding (Python's `key=` does the same), which also keeps the comparator cheap.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL