-
Notifications
You must be signed in to change notification settings - Fork 19
Open
Labels
Description
The policy evaluation produces currently a sarif report with duplicate result entries.
How to reproduce
Here is the rego policy and the command i fired up:
devguard-scanner attestations registry.opencode.de/open-code/oci/debian:13-minimal --policy example.rego
Here is the .rego policy:
# METADATA
# title: example Policy
# custom:
# description: example description
# priority: 1
# predicateType: https://cyclonedx.org/vex
# relatedResources: []
# tags:
# - Legal
# complianceFrameworks: []
package compliance
import rego.v1
# helper functions to extract info from vulnerabilities
# figure out how severe a vulnerability is
# we prefer cvss ratings when available, otherwise use whatever rating comes first
severity(vulnerability) := lower(rating.severity) if {
some rating in vulnerability.ratings
startswith(rating.method, "CVSS")
} else := lower(vulnerability.ratings[0].severity) if {
count(vulnerability.ratings) > 0
}
# check if this vulnerability actually affects us
is_exploitable(vulnerability) if {
vulnerability.analysis.state == "exploitable"
}
# check if we're still figuring out if this vulnerability matters
is_in_triage(vulnerability) if {
vulnerability.analysis.state == "in_triage"
}
# check if someone marked this as a false alarm
is_false_positive(vulnerability) if {
vulnerability.analysis.justification == "false_positive"
}
# check if vulnerability is unhandled (either exploitable or open)
is_affected(vuln) if is_exploitable(vuln)
is_affected(vuln) if is_in_triage(vuln)
# then use it simply
in_triage_vulns := [vuln |
vuln := input.vulnerabilities[_]
is_in_triage(vuln)
]
# list all critical or high vulnerabilities still being investigated
high_or_critical_in_triage_vulns := [vuln |
vuln := in_triage_vulns[_]
severity(vuln) in {"critical", "high"}
]
# count how many got dismissed as false positives
cve_false_positive := count([vuln |
vuln := input.vulnerabilities[_]
is_false_positive(vuln)
])
# count vulnerabilities that match a severity level and are exploitable
count_exploitable_or_open(severity_level) := count([vuln |
vuln := input.vulnerabilities[_]
severity(vuln) == severity_level
is_affected(vuln)
])
# build violation messages for each unhandled vulnerability
violations := [sprintf("%s (%s severity) is in triage and must be handled.", [vuln.id, severity(vuln)]) | vuln := high_or_critical_in_triage_vulns[_]]
cve_critical := count_exploitable_or_open("critical")
cve_high := count_exploitable_or_open("high")
cve_medium := count_exploitable_or_open("medium")
cve_low := count_exploitable_or_open("low")
cve_open := count(in_triage_vulns)
# figure out when the last update happened
# grab all the timestamps we can find from the vulnerability data
all_timestamps := [timestamp |
vuln := input.vulnerabilities[_]
timestamp := [vuln.analysis.lastUpdated, vuln.analysis.firstIssued][_]
timestamp != ""
]
# find the most recent one
last_update := max([time.parse_rfc3339_ns(ts) | ts := all_timestamps[_]]) if {
count(all_timestamps) > 0
} else := 0
# decide if the container is compliant
# rule is simple: no critical or high severity exploitable vulnerabilities allowed
default compliant := false
compliant := true if {
count(high_or_critical_in_triage_vulns) == 0
}
# put everything together in the final result
result := {
"compliant": compliant,
"violations": violations,
"cve_critical": cve_critical,
"cve_high": cve_high,
"cve_medium": cve_medium,
"cve_low": cve_low,
"cve_open": cve_open,
"cve_false_positive": cve_false_positive,
"last_update_unix": last_update / 1000 / 1000,
}# output with duplicate results
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [
{
"results": [
{
"kind": "pass",
"locations": [
{
"message": {
"text": "The attestation is compliant with the policy."
},
"physicalLocation": {
"artifactLocation": {
"description": {
"text": ""
},
"uri": "oci://registry.opencode.de/open-code/oci/debian:13-minimal"
}
}
}
],
"message": {
"text": "Policy compliant"
},
"properties": {
"tags": [
"Legal"
],
"AdditionalProperties": {
"precision": "high"
}
},
"ruleID": "example.rego"
},
{
"kind": "pass",
"locations": [
{
"message": {
"text": "The attestation is compliant with the policy."
},
"physicalLocation": {
"artifactLocation": {
"description": {
"text": ""
},
"uri": "oci://registry.opencode.de/open-code/oci/debian:13-minimal"
}
}
}
],
"message": {
"text": "Policy compliant"
},
"properties": {
"tags": [
"Legal"
],
"AdditionalProperties": {
"precision": "high"
}
},
"ruleID": "example.rego"
},
{
"kind": "pass",
"locations": [
{
"message": {
"text": "The attestation is compliant with the policy."
},
"physicalLocation": {
"artifactLocation": {
"description": {
"text": ""
},
"uri": "oci://registry.opencode.de/open-code/oci/debian:13-minimal"
}
}
}
],
"message": {
"text": "Policy compliant"
},
"properties": {
"tags": [
"Legal"
],
"AdditionalProperties": {
"precision": "high"
}
},
"ruleID": "example.rego"
},
{
"kind": "pass",
"locations": [
{
"message": {
"text": "The attestation is compliant with the policy."
},
"physicalLocation": {
"artifactLocation": {
"description": {
"text": ""
},
"uri": "oci://registry.opencode.de/open-code/oci/debian:13-minimal"
}
}
}
],
"message": {
"text": "Policy compliant"
},
"properties": {
"tags": [
"Legal"
],
"AdditionalProperties": {
"precision": "high"
}
},
"ruleID": "example.rego"
}
],
"tool": {
"driver": {
"name": "devguard-attestations",
"rules": [
{
"fullDescription": {
"text": "Example description"
},
"help": {
"text": "Example description"
},
"id": "example.rego",
"name": "example Policy",
"properties": {
"tags": [
"Legal"
],
"AdditionalProperties": {
"complianceFrameworks": [],
"predicateType": "https://cyclonedx.org/vex",
"priority": 1,
"relatedResources": []
}
},
"shortDescription": {
"text": "example Policy"
}
}
]
}
}
}
],
"version": "2.1.0"
}