---
title: "Custom roles and permissions"
---

Every ((role)) in runZero is a set of permissions. The [built-in roles](managing-your-team.md#available-roles) are fixed sets that cover the common cases. A ((custom role)) is a set you define yourself, so you can grant exactly the access a team needs instead of rounding up to Administrator or down to Viewer.

Custom roles are defined once for the whole client account and can then be assigned anywhere a built-in role can: as a user's default role, as a per-organization role for a user or a [group](managing-user-groups.md), as the [SSO enrollment default](implementing-sso.md), or locked to an [API client](api-clients.md).

The console URLs in this article use `console.runzero.com` as an example. Use the URL for your runZero deployment instead.

## How permissions work {#permission-model}

A permission is a ((verb)) applied to an ((area)). An area is a family of records or settings, such as inventory or alerts. A verb says what may be done to it.

### Verbs

Verbs are ranked, and a higher verb includes every lower one. Granting `write` on an area also grants `annotate` and `read` on that area.

| Verb | What it allows |
| ---- | -------------- |
| Read | Read, search, list, view detail, and export existing records. Nothing changes. |
| Annotate | Change user-supplied metadata on a record you can already read: tags, comments, ownership, criticality, and issue status. It never changes scan-derived facts or configuration. |
| Write | Create, change, and delete records, and run operations that change data. |
| Manage | Change the settings that govern an area for everyone else, and create or change credentials, permissions, and organization structure. |

Only inventory and findings have anything that can be annotated. Every other area goes straight from read to write.

### Areas {#permission-matrix}

| Area | Covers | Verbs available |
| ---- | ------- | --------------- |
| `inventory` | Assets, services, software, certificates, and sites. | read, annotate, write, manage |
| `findings` | Vulnerabilities and issues. | read, annotate, write, manage |
| `tasks` | Scan tasks, scan templates, and raw task artifacts. | read, write, manage |
| `events` | The activity record. Append-only, so read is the only verb. | read |
| `alerts` | Alert rules, notification channels, and alert templates. | read, write, manage |
| `explorers` | Explorers, explorer groups, and hosted zones. | read, write, manage |
| `sources` | Integration sources and custom integrations. | read, write, manage |
| `queries` | The saved query library, including the Rapid Response feed. | read, write, manage |
| `directory` | Directory user and group records collected by integrations and scans. Harvested data, so read is the only verb. | read |
| `users` | Console users, user groups, and invitations. | read, write, manage |
| `organizations` | Organizations, their settings, and their hierarchy. | read, write, manage |
| `credentials` | The credentials runZero uses to authenticate scans and integrations. | read, write, manage |
| `tokens` | API keys, export tokens, and API clients. | read, manage |
| `ai` | AI Hub, AI threads, and query translation. | read, write, manage |
| `reports` | Reports, external reporting, and goals. | read, write, manage |
| `account` | Account settings and license information. | read, manage |
| `content` | Reference content runZero ships, such as vulnerability match rules and scan checks. Read-only for everyone. | read |

Four distinctions are worth reading twice, because the names are similar and the access is not:

- **`users` is console identity. `directory` is collected data.** `users` covers the people who sign in to your console. `directory` covers the user and group records that scans and integrations bring back from LDAP, Entra ID, and similar sources. Granting one does not grant the other.
- **`credentials` is scan credentials. `tokens` is API credentials.** `credentials` covers the secrets runZero uses to log in to your systems. `tokens` covers the keys and clients that let something log in to runZero. A credential that can create another credential is a way to escalate privilege, so keep `tokens` restricted.
- **`tasks` includes raw scan artifacts.** A raw artifact includes the inventory and directory records the scan collected, so `tasks:read` reaches that data without a separate `inventory` or `directory` grant.
- **Permission is not the same as visibility.** A permission says what you may do; the organizations attached to the assignment say where. Both apply on every request.

### What the verbs mean in practice

The same permissions drive the console, the [API](leveraging-the-api.md), and [MCP](mcp.md). If a role cannot write inventory, the buttons that write inventory are not offered in the console, the matching API routes refuse the call, and the MCP tools that would change inventory are not offered to the AI client. There is no surface where a permission is enforced in one place and not another.

Some worked examples, for the areas where the line between verbs matters most:

| Permission | What it allows |
| ---------- | -------------- |
| `inventory:read` | Search and view assets, services, software, certificates, and sites, and export them. |
| `inventory:annotate` | The above, plus tagging assets, setting ownership and criticality, and adding comments. |
| `inventory:write` | The above, plus editing and deleting assets, and moving them between sites. |
| `inventory:manage` | The above, plus bulk deletion and the inventory settings that apply to everyone. |
| `tasks:read` | View scan and integration task history, and download raw task artifacts, which include the inventory and directory data those scans collected. |
| `tasks:write` | Start, stop, and delete scans. |
| `tasks:manage` | The above, plus creating and changing scan templates. |
| `findings:annotate` | Change issue status and suppression state without changing the underlying findings. |
| `sources:write` | Configure and run integration sources. |
| `sources:manage` | The above, plus custom integrations. |
| `users:read` | See who is on the team and what access they have. |
| `users:manage` | Invite, change, and remove console users and groups. This is the permission that makes someone an administrator of an organization. |
| `tokens:read` | See which API credentials exist. |
| `tokens:manage` | Create, change, and revoke API keys, export tokens, and API clients, and approve [MCP connections](mcp.md#mcp-oauth). |
| `credentials:manage` | Create, change, and delete the credentials used to authenticate scans, and list them through the API and MCP. Secret values are never returned by any permission. |

An export always requires the same permission as reading the data in the console. There is no separate export permission to grant or withhold.

### What a custom role cannot grant {#structural-privileges}

Some privileges are structural and are never part of a role's permissions:

- **Superuser.** Global settings, subscriptions, and SSO configuration.
- **Billing.** Licensing, billing, and entity settings, which stay with the built-in Billing role.
- **Account settings.** The `account` area is reserved for built-in roles, so a custom role cannot grant it.
- **Managing roles.** A custom role can never authorize changes to roles, including its own permissions.

## What the built-in roles grant {#built-in-role-permissions}

The built-in roles are the same permission model expressed as fixed sets. This table is useful as a starting point when deciding which permissions a custom role should include. A dash means no access to that area.

| Area | Administrator | User | Annotator | Viewer | Billing |
| --- | --- | --- | --- | --- | --- |
| `inventory` | manage | write | annotate | read | - |
| `findings` | manage | write | annotate | read | - |
| `tasks` | manage | manage | - | - | - |
| `events` | read | read | read | read | - |
| `alerts` | manage | manage | read | read | - |
| `explorers` | manage | write | read | read | - |
| `sources` | manage | write | read | read | - |
| `queries` | manage | read | read | read | - |
| `directory` | read | read | read | read | - |
| `users` | manage | read | read | read | - |
| `organizations` | manage | read | read | read | - |
| `credentials` | manage | - | - | - | - |
| `tokens` | manage | read | - | - | - |
| `ai` | manage | write | write | write | - |
| `reports` | manage | write | read | read | - |
| `account` | read | read | read | read | manage |
| `content` | read | read | read | read | - |

Superuser is not in this table because it is a flag on a user rather than a role.

## Creating a custom role {#creating}

Custom roles are managed from the **Roles** page under **Account** in the left navigator, at [console.runzero.com/account/roles](https://console.runzero.com/account/roles). If the page is not in your navigator, either you do not administer every organization or custom roles are not enabled for your account. The page lists the built-in roles as read-only rows alongside your custom roles, with the permissions each one grants and, for the people who manage roles, how many users, groups, and API clients are assigned the role.

The Roles page is available to superusers and to all-organization administrators, who are also the only people who can create, change, or delete a role. Everyone else can still read the role catalog, which is what lets the role dropdowns and effective-access views elsewhere in the console explain what each role allows.

To create one:

1. Click **Create role**.
2. Give it a **Name**. Names are 2 to 64 characters of letters, digits, spaces, underscores, periods, and hyphens, and must start with a letter or digit. They are unique within the account without regard to case, and cannot reuse a built-in role name or label.
3. Add a **Description**. This is the help text shown to whoever assigns the role, so describe what the role is for rather than restating the permissions.
4. Set the **Permissions**. Choose a verb for each area you want the role to grant, and leave the rest at no access. The `account` area is not offered.
5. Save. A role has to grant at least one permission.

You can also use the copy action on an existing row to start from another role's permissions, which is the quickest way to build a role that is "Viewer, plus one thing".

### Editing, renaming, and deleting {#editing}

Editing a role changes access immediately for everyone assigned that role. There is no separate publish step.

Renaming a role rewrites every assignment that refers to it, including SSO enrollment defaults and API client locks, so nothing is orphaned. Renaming onto a name that still has assignments is refused rather than merging the two.

Deleting a role leaves its name on the assignments that used it, but the role stops contributing any permission. Those assignments display as disabled, and effective access views show "No access" with a note that the role has been disabled. Other roles assigned to a user continue to apply. The delete confirmation lists the users, groups, API clients, and organizations affected.

Two consequences are worth planning for:

- **An API client locked to a deleted role cannot authenticate** until a role with that name exists again.
- **Recreating a role with the same name re-enables every assignment that still refers to it.** The create form warns you when a name still has assignments and asks you to confirm. This is deliberate, so that deleting a role by mistake can be undone, but the name itself retains authority. Treat recreating a deleted role name with the same care as granting the access directly.

## Assigning custom roles {#assigning}

A custom role appears in every role dropdown that a built-in role appears in, with its description as help text. Nothing about how you assign roles changes.

### To a user

On the [Your team](https://console.runzero.com/team) page, use the gear icon on a user's row, or the button on their user details page, to edit their permissions. You can set a custom role as the user's default role in every organization, or per organization.

The user details page continues to show effective access per organization, split into direct user access, group access, and SSO group access, so you can see what a role actually resolves to for that person.

### To a group

[User groups](managing-user-groups.md) take custom roles the same way, either as the group's default role in every organization or per organization. Group membership can come from the console or from [SSO group mappings](managing-sso-group-mappings.md).

### As the SSO enrollment default

The **Default role in any organization** field on the [SSO settings](https://console.runzero.com/team/sso/idp/) page accepts custom roles as well as built-in ones. Users provisioned through SSO enroll with that role.

If the role has been deleted by the time a new user enrolls, they enroll with no access rather than inheriting something unintended, and the event is recorded. Recreating the role does not retroactively change users who already enrolled, though it does re-enable their stored assignment.

### To an API client

An [API client](api-clients.md) can be locked to a role, so that the credential's access follows later changes to that role, or can use a role as a starting point for a one-off set of permissions. See [Role locks](api-clients.md#role-locks).

## How multiple roles combine {#effective-access}

A user can be assigned roles through several routes at once: their own default role, a per-organization role, a group's default role, and a group's per-organization role.

**Permissions add together.** In a given organization, the user gets the best built-in role that applies plus every custom role that applies, unioned. Where two roles grant different verbs on the same area, the higher one wins. A custom role can only add access, and never reduces what a built-in role already grants. If someone has Viewer by default and a custom role granting `tasks:write` in one organization, they can start scans in that organization and remain a viewer everywhere else.

**A custom role can bring an organization into view.** If the only thing granting a user access to an organization is a custom role, that organization appears in their organization picker and in their effective access.

**Custom roles never confer structural privileges.** No combination of custom roles makes someone a superuser, gives them billing access, or lets them manage roles. See [What a custom role cannot grant](custom-roles.md#structural-privileges).

Each role slot contains one role. Assigning a new role to a user's default slot replaces the role that was there. To give someone several distinct sets of permissions, combine a default role with per-organization roles, or with group membership.

## Auditing {#auditing}

Role changes are recorded in the [audit log](managing-your-team.md#audit-log) as `role-created`, `role-updated`, and `role-deleted` events. An update records which fields changed, including the previous name and permissions. A delete records how many assignments were disabled.

On the Roles page, the usage columns and the usage view list the users, groups, and API clients assigned each role, and whether it is the SSO enrollment default.
