> For the complete documentation index, see [llms.txt](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/features/access-reviews/how-to/access-path-risk-score.md).

# Access Path Risk Score

## Overview

Access reviews that use [Access Intelligence](/4yItIzMvkpAvMVFAamTf/features/insights/risks.md) include a **Risk Score** column in the reviewer interface. Each row carries one score that consolidates the risk signals along the entire access path: the source identity, any intermediate groups or roles, and the destination resource.

The individual risk columns for source users, destination resources, and intermediate entities still tell you the per-entity story. The Risk Score condenses it into one column that you can sort, filter, and prioritize on.

{% hint style="info" %}
**Prerequisite**: Access Intelligence must be enabled on the review configuration for Risk Scores to appear. See [1-Step Access Reviews](/4yItIzMvkpAvMVFAamTf/features/access-reviews/configuration/1-step-review.md) or the [Access Reviews Query Builder](/4yItIzMvkpAvMVFAamTf/features/access-reviews/configuration/access-reviews-query-builder.md) to enable it.
{% endhint %}

## How risk scores are calculated

A typical access path looks like the following:

```mermaid
flowchart LR
  IdP[IdP user<br/>enrichment]
  P[Source identity<br/>e.g. user]
  R1[Role or group<br/>intermediate node]
  R2[Permission<br/>intermediate node]
  D[Destination<br/>resource]

  IdP -.joined.-> P
  P --> R1 --> R2 --> D

  classDef contrib fill:#e6f4ea,stroke:#1e8e3e
  classDef join fill:#fef7e0,stroke:#f9ab00
  class P,R1,R2,D contrib
  class IdP join
```

A full access path risk score calculation combines the `risk_score` properties of the entities that make up the path:

| Input                          | Source                                                                                                                                                                                               |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Source identity score**      | The principal of the path (typically a user). If an enrichment node is joined to the principal (for example, an IdP user joined to a local user), the **higher** of the two scores is used.          |
| **Destination resource score** | The terminal node of the path (the resource being accessed).                                                                                                                                         |
| **Intermediate node score**    | The **highest** score among the roles, groups, and other entities that appear in the path summary. Only that one node contributes, so a long chain of low-risk hops does not dilute the path's risk. |

Entities with no risk score in the relevant snapshot are skipped.

Scores are **snapshot-based**: Veza calculates each one when the review is created, after the assessment query runs, so that every per-entity risk score along the path is available first. Scores are not recalculated when the underlying data changes. The score is a whole number from **0 to 100**.

### Formula

Given the set of input scores `s₁, s₂, … sₙ`, Veza derives the consolidated score in three steps:

1. **Combine the inputs.** Square each input, sum the squares, and take the square root. This root-sum-of-squares aggregation weights the largest contributors most heavily, and the total grows as more high-risk entities appear on the same path.

   ```
   base = √(s₁² + s₂² + … + sₙ²)
   ```
2. **Apply enhancer multipliers.** Each enhancer has an *applicability* condition, which determines whether the path carries the data needed to evaluate it, and a *trigger* condition, which determines whether that data meets the enhancer's threshold. Each enhancer whose trigger condition is met multiplies the base by **2.0**.

   | Enhancer                           | Applicable when                                                                                                                                       | Triggered when                                                                                                                                                        |
   | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   | **Write or delete permissions**    | The path has at least one data or metadata permission (read, write, create, or delete). Membership-only paths (Uncategorized / NonData) are excluded. | At least one of those permissions is a write, create, or delete (on data or metadata).                                                                                |
   | **Identity inactive for 90+ days** | The source identity carries a last-active timestamp: `last_login_at` for IdP users, or `last_used_at` for other identity types.                       | That timestamp is more than 90 days old. A dormant identity that still holds access is a stronger staleness signal than how recently the access itself was exercised. |

   Both enhancers can be triggered on the same path, compounding to a `4.0×` multiplier.
3. **Normalize to 0–100.** Divide by the maximum value the formula could have produced for a path with the same number of nodes and the same set of *applicable* enhancers:

   ```
   max_base     = 100 × √n
   max_enhanced = max_base × (product of applicable enhancer multipliers)
   score        = round( (base × enhancer) / max_enhanced × 100 )
   ```

   The maximum denominator counts every *applicable* enhancer, including those the path did not trigger.

   For example, a path that carries read-only data permissions makes the write/delete enhancer applicable, contributing ×2.0 to the denominator even though the enhancer's trigger condition is not met.

   To keep paths with comparable structure on the same scale, membership-only paths (no data or metadata permissions on the path) skip the write/delete enhancer from both numerator and denominator.

The final score is rounded to the nearest whole number and capped at 100.

### Examples

#### Example 1: High-risk user with read-only access to a sensitive resource

A user with `risk_score = 99` is assigned to a role with `risk_score = 53`. The role grants a read-only data permission on the destination resource, which itself has no risk score in the snapshot. The user carries no last-active timestamp in the snapshot, so the inactivity enhancer is not applicable.

* Inputs: `s = [99, 53]`, so `n = 2`
* `base = √(99² + 53²) ≈ 112.3`
* Write/delete enhancer applicable (data read present), not triggered: `enhancer = 1.0`, `max_enhancer_product = 2.0`
* `max_base = 100 × √2 ≈ 141.4`, `max_enhanced ≈ 282.8`
* `score = round( 112.3 / 282.8 × 100 ) = 40`

#### Example 2: IdP-enriched user with read-only access and a low-risk destination

The local user has a low risk score, but the joined IdP user has `risk_score = 75`. The path terminates on a resource with `risk_score = 0`. The destination grants read-only data permissions, and neither identity carries a last-active timestamp.

* Inputs: `s = [75, 0]` (the max of local user and IdP user is used), so `n = 2`
* `base = √(75² + 0²) = 75`
* Write/delete enhancer applicable (data read present), not triggered: `enhancer = 1.0`, `max_enhancer_product = 2.0`
* `max_base = 100 × √2 ≈ 141.4`, `max_enhanced ≈ 282.8`
* `score = round( 75 / 282.8 × 100 ) = 27`

A path can therefore score well below its highest single input. Normalization reserves room for the *potential* contribution of an enhancer whenever the data to evaluate it is present, even when the trigger condition is not met.

#### Example 3: IdP-enriched user on a membership-only path

Same identity inputs as Example 2 (local user low, joined IdP user `risk_score = 75`, destination `risk_score = 0`), but the path is a role or group assignment. Permissions on the path are membership only (Uncategorized / NonData). Neither identity carries a last-active timestamp.

* Inputs: `s = [75, 0]`, so `n = 2`
* `base = √(75² + 0²) = 75`
* Write/delete enhancer **not applicable** (no data or metadata permissions): `enhancer = 1.0`, `max_enhancer_product = 1.0`
* `max_base = 100 × √2 ≈ 141.4`, `max_enhanced ≈ 141.4`
* `score = round( 75 / 141.4 × 100 ) = 53`

Compared to Example 2, the same identity inputs produce a higher score because membership-only paths do not reserve room in the denominator for an enhancer that cannot be triggered.

#### Example 4: Write access held by a dormant user

A user with `risk_score = 80` has a write data permission on a resource with `risk_score = 60` via a role with `risk_score = 40`. The user last signed in more than 90 days ago.

* Inputs: `s = [80, 60, 40]`, so `n = 3`
* `base = √(80² + 60² + 40²) ≈ 107.7`
* Write enhancer triggered (`× 2.0`), identity-inactivity enhancer triggered (`× 2.0`): `enhancer = 4.0`, `max_enhancer_product = 4.0`
* `enhanced = 107.7 × 4.0 ≈ 430.8`
* `max_base = 100 × √3 ≈ 173.2`, `max_enhanced ≈ 692.8`
* `score = round( 430.8 / 692.8 × 100 ) = 62`

## How outlier detection raises the score

When [outlier detection](/4yItIzMvkpAvMVFAamTf/features/access-reviews/configuration/access-review-settings.md#outlier-detection) is enabled on a review, Veza multiplies the Risk Score of each flagged access path by **1.25**, rounds the result to the nearest whole number (a half rounds upward), and caps it at **100**. A path scoring 40 is recorded as 50, and one scoring 79 is recorded as 99. Any path scoring 80 or above before the boost is recorded as 100.

Veza applies this multiplier to the normalized 0–100 score. It is not one of the enhancer multipliers described above, and it does not alter how the base score is calculated.

The boost applies only to the paths that outlier detection flags. The following retain their original score:

* A path that outlier detection evaluated but did not flag
* A path for which outlier detection produced no prediction
* A flagged path whose Risk Score is 0

Because the Risk Level tier derives from the final score, the boost can promote a row to a higher tier. A path scoring 60 falls in the **High** band; boosted to 75, the same row lands in **Critical**.

The boosted value is the score shown in the **Risk Score** column, the **Risk Level** column, and the row details panel, and the value written to the `access_path_risk_score` field in CSV and XLSX exports. As with every other Risk Score, Veza calculates it once at review creation and stores it in the review snapshot.

{% hint style="info" %}
Outlier detection is an Early Access feature configured through the API. On tenants where it is not enabled, no path is flagged and no Risk Score is boosted. The boost applies to Access Reviews created in Veza v2026.8.24-1 and later. See [Outlier Detection](/4yItIzMvkpAvMVFAamTf/developers/api/workflows/access-review-settings/outlierdetection.md) for the configuration API, peer grouping, and thresholds.
{% endhint %}

## Risk level tiers

The numeric Risk Score maps to a risk level tier:

{% hint style="info" %}
These thresholds apply to Access Reviews created in Veza v2026.5.18-1 and later. Reviews created in earlier versions retain the legacy risk level bands.
{% endhint %}

| Score range | Risk level |
| ----------- | ---------- |
| ≥ 75        | Critical   |
| 50–74       | High       |
| 25–49       | Medium     |
| 10–24       | Low        |
| < 10        | None       |

## Risk Score in the reviewer interface

### Display

Each row displays the score as a color-coded number: lower scores appear in muted tones, and higher scores appear in progressively stronger colors (orange through red) to draw attention to elevated risk.

A **Risk Level** column (Critical / High / Medium / Low) is shown alongside it, derived from the same access path risk score using the tiers above.

Clicking a Risk Score value in the table opens the row details panel to the **Risks** tab, where individual entity risk scores and contributing risk factors are listed.

### Sorting and filtering

The **Risk Score** column supports:

* **Sorting** — click the column header to sort ascending or descending by numeric score
* **Filtering** — filter by exact score value, by range (greater than, less than, etc.), or by **Risk Level** tier (Critical, High, Medium, Low)

### Row details

The row details panel shows the **Risk Score** prominently. The **Risks** tab lists all individual entity risk scores and contributing risk factors for every entity in the access path, providing full explainability for what drove the score.

## Exporting risk scores

The `access_path_risk_score` field is included as an integer in both CSV and XLSX exports. To export review rows, see [Exporting review rows](/4yItIzMvkpAvMVFAamTf/features/access-reviews/how-to/reviewer-interface.md#exporting-review-rows).

## Backward compatibility

Risk Scores are only available on reviews created after this feature was released. The **Risk Score** column does not appear for older reviews to avoid showing empty values. Those reviews continue to display per-entity risk score columns and the Risk Level column as before.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/features/access-reviews/how-to/access-path-risk-score.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
