Simplify CVSS code in a more object-oriented manner

This commit is contained in:
maride 2026-01-28 13:35:45 +01:00
parent de6dcf2b82
commit 98c0f72e0d
2 changed files with 31 additions and 49 deletions

View File

@ -4,50 +4,32 @@
#let isUsed = state("isUsed", false)
// Statistics, used e.g. for the management summary
#let riskCategoryStats = (
Critical: state("riskCriticalStat", 0),
High: state("riskHighStat", 0),
Medium: state("riskMediumStat", 0),
Low: state("riskLowStat", 0),
None: state("riskInformativeStat", 0),
Other: state("riskOtherStat", 0)
#let riskCategories = (
"CRITICAL": (color: red, title: "Critical", state: state("riskCriticalStat", 0)),
"HIGH": (color: orange, title: "High", state: state("riskHighStat", 0)),
"MEDIUM": (color: yellow, title: "Medium", state: state("riskMediumStat", 0)),
"LOW": (color: lime, title: "Low", state: state("riskLowStat", 0)),
"NONE": (color: white, title: "None", state: state("riskInformativeStat", 0)),
"OTHER": (color: gray, title: "Other", state: state("riskOtherStat", 0))
)
// Function to update the statistics
#let updateRiskCategoryStats(status) = {
status = upper(status)
// check argument
panicOnInvalid(status, riskCategories.keys())
// Update status
if status == "Critical" {
context(riskCategoryStats.Critical.update(v => v + 1))
} else if status == "High" {
context(riskCategoryStats.High.update(v => v + 1))
} else if status == "Medium" {
context(riskCategoryStats.Medium.update(v => v + 1))
} else if status == "Low" {
context(riskCategoryStats.Low.update(v => v + 1))
} else if status == "None" {
context(riskCategoryStats.None.update(v => v + 1))
} else if status == "Other" {
context(riskCategoryStats.Other.update(v => v + 1))
} else {
panic("Unknown state: " + status)
}
context(riskCategories.at(status).state.update(v => v + 1))
}
// Return the table cell formatted according to its content - for the CVSS result
#let colorize(str) = {
if str == "Critical" {
table.cell(str, fill: red, align: center)
} else if str == "High" {
table.cell(str, fill: orange, align: center)
} else if str == "Medium" {
table.cell(str, fill: yellow, align: center)
} else if str == "Low" {
table.cell(str, fill: lime, align: center)
} else if str == "None" {
table.cell(str, fill: white, align: center)
} else {
panic("Unknown CVSS state: " + str)
}
#let coloredCell(status) = {
status = upper(status)
// check argument
panicOnInvalid(status, riskCategories.keys())
table.cell(riskCategories.at(status).title, fill: riskCategories.at(status).color, align: center)
}
// Create a small CIA table to be included for every finding
@ -75,15 +57,15 @@
let status = "?"
if baseScore >= 9.0 {
status = "Critical"
status = "CRITICAL"
} else if baseScore >= 7.0 {
status = "High"
status = "HIGH"
} else if baseScore >= 4.0 {
status = "Medium"
status = "MEDIUM"
} else if baseScore >= 0.1 {
status = "Low"
status = "LOW"
} else {
status = "None"
status = "NONE"
}
block(
@ -98,7 +80,7 @@
table.cell(colspan: 3)[*Impact Metrics*],
table.cell(rowspan: 2, align: bottom)[*#sym.sum*],
[*AV*], [*AC*], [*PR*], [*UI*], [*S*], [*C*], [*I*], [*A*],
attackVector, attackComplexity, privilegesRequired, userInteraction, scope, cia.colorize(confidentiality), cia.colorize(integrity), cia.colorize(availability), colorize(status),
attackVector, attackComplexity, privilegesRequired, userInteraction, scope, cia.colorize(confidentiality), cia.colorize(integrity), cia.colorize(availability), coloredCell(status),
)
)
#align(right)[

View File

@ -25,7 +25,7 @@
== Findings
The penetration test revealed #context([
#let num = cvss.riskCategoryStats.values().map(v => v.final()).sum()
#let num = cvss.riskCategories.values().map(v => v.state.final()).sum()
#if num == 1 {
[ #num finding ]
} else {
@ -37,12 +37,12 @@
columns: (16.66%, 16.66%, 16.66%, 16.66%, 16.66%, 16.66%),
align: center,
[Critical], [High], [Medium], [Low], [None], [Other],
table.cell(context(cvss.riskCategoryStats.Critical.final()), fill: red, align: center),
table.cell(context(cvss.riskCategoryStats.High.final()), fill: orange, align: center),
table.cell(context(cvss.riskCategoryStats.Medium.final()), fill: yellow, align: center),
table.cell(context(cvss.riskCategoryStats.Low.final()), fill: lime, align: center),
table.cell(context(cvss.riskCategoryStats.None.final()), fill: white, align: center),
table.cell(context(cvss.riskCategoryStats.Other.final()), fill: gray, align: center),
table.cell(context(cvss.riskCategories.at("CRITICAL").state.final()), fill: red, align: center),
table.cell(context(cvss.riskCategories.at("HIGH").state.final()), fill: orange, align: center),
table.cell(context(cvss.riskCategories.at("MEDIUM").state.final()), fill: yellow, align: center),
table.cell(context(cvss.riskCategories.at("LOW").state.final()), fill: lime, align: center),
table.cell(context(cvss.riskCategories.at("NONE").state.final()), fill: white, align: center),
table.cell(context(cvss.riskCategories.at("OTHER").state.final()), fill: gray, align: center),
)
== Recommendations & Next Steps