Skip to content

Risk strategies

The ordered rule list that puts every open finding in a priority tier, every metric and operator a rule can use, the system default ladder, and the API to edit your own.

Updated 02 Nov 2026Checked against vdb-site@1a06d67, saas@50cedf3

A risk strategy is an ordered list of rules. Each open finding gets the priority tier of the first rule it matches: tier 0 is the most urgent. A finding that matches no rule sorts last. Within a tier, older findings come first.

The tier drives GET /v1/findings?sort=priority and the risk-priority and ownership widgets. Edit strategies on Configuration › Risk Prioritization (/resolve/risk-strategy).

Which strategy applies

  • Vulnetix ships one System Default strategy. It is read-only and applies to every organisation without an active strategy of its own.
  • Your organisation may own several strategies. At most one is active. Activating one deactivates the others in the same write.
  • To start from the default, create a strategy with cloneFrom set to its id (or omit cloneFrom: a new strategy copies the system default’s rules).

Rules

A rule is {metric, operator, thresholdLow, thresholdHigh, label, enabled}, plus attackPathId for ATTACK_PATH. Its position in the list is its tier.

Metrics

Metric Matches when Operators
MALWARE The finding is a known-malicious package IS_TRUE
KEV_CISA The vulnerability is in the CISA KEV catalogue IS_TRUE
KEV_ENISA It is in the ENISA EU KEV catalogue IS_TRUE
KEV_VULNETIX It is in the Vulnetix KEV catalogue IS_TRUE
KEV_VULNCHECK It is in the VulnCheck KEV catalogue IS_TRUE
EXPLOIT_WEAPONIZED Exploit intelligence has a weaponised entry IS_TRUE
EXPLOIT_ACTIVE Exploit intelligence has an active sighting IS_TRUE
EXPLOIT_POC Exploit intelligence has a proof of concept IS_TRUE
INTERNET_EXPOSED_PACKAGE The finding’s package was observed on a publicly reachable cloud resource attributed to its repository IS_TRUE
INTERNET_EXPOSED The finding’s repository has at least one publicly reachable cloud resource IS_TRUE
REACHABLE CLI reachability analysis proved the vulnerable code is called. SCA findings only. IS_TRUE
UNREACHABLE Reachability was assessed and found the code unreachable. Not the same as never assessed. IS_TRUE
TRACEABLE A SAST or secrets finding resolves to a file and line range IS_TRUE
TRACEABLE_GRAPH Traceable, and the file is called in the repository’s insights graph IS_TRUE
ATTACK_PATH The finding matches the named attack path IS_TRUE
CVSS Effective CVSS score, 0 to 10. A custom score is preferred over the vendor’s. numeric
CWSS Effective CWSS score. A custom score is preferred. numeric
CUSTOM_CVSS The analyst’s custom CVSS score only. A finding with none never matches. numeric
CUSTOM_CWSS The analyst’s custom CWSS score only numeric
CESS Coalition Exploit Scoring System prediction, 0 to 10 numeric
EPSS EPSS probability, 0 to 1 numeric
REMAINING Everything. Must appear exactly once. ALWAYS

The schema also defines VULNETIX_POC_VERIFIED (Vulnetix verified a PoC from the published patch) and VULNETIX_NO_EXPLOIT_PATH (Vulnetix found no exploit path from the patch and none is public), but the API does not accept them in a rule yet: a save that uses either is 400 invalid metric.

Custom scores are set on a finding with PATCH /v1/findings/{uuid}/score; see Findings and triage. The two internet-exposure metrics use the same matching as the finding page’s Attack Surface tab; see Internet exposure.

Operators

Operator Meaning Needs
IS_TRUE The boolean metric holds nothing
GTE score >= thresholdLow thresholdLow
GT score > thresholdLow thresholdLow
LTE score <= thresholdLow thresholdLow
LT score < thresholdLow thresholdLow
BETWEEN thresholdLow <= score <= thresholdHigh both
ALWAYS matches everything nothing; used by REMAINING

Thresholds are on the metric’s own scale: EPSS 0.79, not 79.

Validation

A rules save is refused with 400 and the first problem:

Message Cause
at least one rule is required empty list
invalid metric: X, invalid operator: X not in the tables above
exactly one REMAINING rule is required none, or more than one
an ATTACK_PATH rule must name an attack path ATTACK_PATH without attackPathId
attackPathId is only valid on an ATTACK_PATH rule attackPathId on another metric
BETWEEN requires both thresholds
threshold required for GTE (and GT, LTE, LT)

An attackPathId your organisation cannot see is refused the same way as one that does not exist. A rule with an empty label is labelled <METRIC> <OPERATOR>.

The system default ladder

Tier Metric Rule Label
0 MALWARE IS_TRUE Known malware
1 KEV_CISA IS_TRUE CISA KEV listed
2 KEV_ENISA IS_TRUE ENISA EU KEV listed
3 KEV_VULNETIX IS_TRUE Vulnetix KEV listed
4 KEV_VULNCHECK IS_TRUE VulnCheck KEV listed
5 EXPLOIT_WEAPONIZED IS_TRUE Weaponized exploit
6 EXPLOIT_ACTIVE IS_TRUE Active exploitation (sightings)
7 CESS GT 6.3 Coalition ESS > 63%
8 EXPLOIT_POC IS_TRUE PoC exploit
9 CUSTOM_CWSS GTE 9.0 Custom CWSS critical
10 CWSS GTE 9.0 CWSS critical
11 CUSTOM_CVSS GTE 9.0 Custom CVSS critical
12 CUSTOM_CWSS GTE 7.0 Custom CWSS high
13 CUSTOM_CVSS GTE 7.0 Custom CVSS high
14 EPSS GT 0.79 EPSS > 79%
15 CESS BETWEEN 3.0 6.3 Coalition ESS 30-63%
16 CWSS GTE 7.0 CWSS high
17 CVSS GTE 9.0 CVSS critical
18 EPSS BETWEEN 0.49 0.79 EPSS 49-79%
19 CVSS GTE 7.0 CVSS high
20 CESS LT 3.0 Coalition ESS < 30%
21 EPSS LTE 0.49 EPSS <= 49%
22 REMAINING ALWAYS All remaining (oldest first)

The default puts exploitation evidence first, then your own custom scores, then predicted likelihood and impact. It does not use the reachability, exposure or attack-path metrics; add them in a strategy of your own.

Attack paths

An attack path is a named chain of attack vectors, shared by the ATTACK_PATH metric and the threat model page. Vulnetix publishes blueprint paths that every organisation can read and none can edit; fork one with ?cloneFrom.

Method Path
GET, POST /v1/attack-paths/
GET, PUT, DELETE /v1/attack-paths/{id}
PUT /v1/attack-paths/{id}/vectors

API

Method Path Body Returns
GET /v1/risk-strategies/ {strategies}: yours and the system default, each with its rules
POST /v1/risk-strategies/ name (required), description, cloneFrom, activate {id}
PUT /v1/risk-strategies/{id} name, description, activate {ok}
DELETE /v1/risk-strategies/{id} {ok}. The system default cannot be deleted.
PUT /v1/risk-strategies/{id}/rules {rules: [...]} {ok, count}. Replaces the whole list; tiers are renumbered 0 to n-1 in array order.
GET /v1/findings/strategy-lens Ten findings ranked three ways (vendor CVSS, EPSS, the active strategy), for the comparison diagram

A strategy you do not own is 404 on PUT and DELETE. Creating a strategy and activating it:

API=https://www.vulnetix.com/api/site/v1
AUTH="Authorization: ApiKey $VULNETIX_ORG_ID:$VULNETIX_API_KEY"

ID=$(curl -sS -X POST "$API/risk-strategies/" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"name":"Exposure first","activate":true}' | jq -r .id)

curl -sS -X PUT "$API/risk-strategies/$ID/rules" -H "$AUTH" -H 'Content-Type: application/json' -d '{"rules":[
  {"metric":"MALWARE","operator":"IS_TRUE","label":"Known malware","enabled":true},
  {"metric":"INTERNET_EXPOSED_PACKAGE","operator":"IS_TRUE","label":"Exposed package","enabled":true},
  {"metric":"KEV_CISA","operator":"IS_TRUE","label":"CISA KEV","enabled":true},
  {"metric":"REACHABLE","operator":"IS_TRUE","label":"Reachable","enabled":true},
  {"metric":"EPSS","operator":"GT","thresholdLow":0.5,"label":"EPSS > 50%","enabled":true},
  {"metric":"REMAINING","operator":"ALWAYS","label":"Everything else","enabled":true}
]}'

A disabled rule (enabled: false) stays in the list and is skipped when ranking.

Edit this pageSources: saas/prisma/models/risk.prisma, vdb-site/api/internal/handler/risk_strategy.go, vdb-site/api/internal/handler/risk_exposure.go, vdb-site/api/internal/handler/findings.go, saas/prisma/migrations/20260720000001_add_risk_prioritization_strategy/migration.sql, saas/prisma/migrations/20260722000002_seed_kev_enisa_default_rule/migration.sql
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.