> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/posture/create-a-custom-monitor.md).

# Create a custom monitor

Build a custom posture monitor in P0 to continuously detect a specific access vulnerability, such as unused privileged grants, across every environment scan.

P0 runs its built-in monitors against your environment on every scan to surface common access vulnerabilities. When you need to enforce a policy that's specific to your organization (for example, flagging unused privileged grants or credentials that violate your rotation policy), you create a custom monitor.

A custom monitor turns an inventory query ([Query search](/inventory/query-search.md)) into a recurring check. P0 re-runs the query on every scan and reports matches as findings in [Monitor results](/posture/monitor-results.md), alongside your built-in monitors.

## Prerequisites

Before you start, make sure you have:

* A P0 account with the **Owner** or **Admin** role. See [Role-based access control](/p0-management/role-based-access-control.md).
* At least one resource integration connected to an environment. See [Resource integrations](/integrations/resource-integrations.md) and [Creating an environment](/getting-started/creating-an-environment.md).
* A completed access scan. If you haven't run one yet, follow [Explore who has access to what with Access Inventory](/getting-started/getting-started-with-access-inventory.md).
* Familiarity with P0 query expressions ([Query search](/inventory/query-search.md)). This guide uses them to define what the monitor detects.

## Build and save the monitor

You create custom monitors from the **Inventory** page, where you can write and test a query before promoting it to a monitor.

1. Select **Inventory** in the P0 app sidebar.
2. Select what the monitor evaluates from the **show** control: `credentials`, `identities`, `entitlements`, or `resources`. For example, select `entitlements` to monitor grants.
3. Enter a query in the **where** field that isolates the vulnerability you want to detect. To find entitlements that grant critical-risk privileges that no one has used, enter:

   ```
   usage:type:"unused"->risk:CRITICAL
   ```

   This matches entitlements connected to an unused privilege that carries a `CRITICAL` risk in the [IAM Privilege Catalog](https://catalog.p0.dev/risks).
4. Review the results. Adjust the query until only the grants you want to flag appear. Select **view** on any result to see its **Query Path**, which shows why the result matched.
5. Select **Save Search**, then select **Create from Scratch** (or **Create from Template** to start from an existing monitor). The **Save This Search** dialog opens.
6. Enable the **Create a monitor for this search?** toggle.
7. Enter a **Monitor Name** and **Description**, set a **Priority**, and select the **Scope** (the integrations the monitor applies to). Write the description so a finding's assignee understands the risk and how to resolve it.
8. Save the monitor.

{% hint style="info" %}
To model a new monitor on an existing one, open a built-in monitor in [Monitor results](/posture/monitor-results.md) and reuse its query as a starting point. For example, the built-in unused service-account key monitor uses `show = credential` with:

```
credential=enabledKey:"true"
credential=last40:"unused"
identity=type:"service-account"
identity=status:"active"
```

{% endhint %}

## Verify the monitor

Confirm the monitor is active and reporting:

1. Select **Posture** in the sidebar.
2. Find your monitor by its name in the monitor list. It appears with the priority you assigned.
3. Select the monitor to open its [Monitor results](/posture/monitor-results.md) page and review the findings from the most recent scan.

P0 re-evaluates the monitor on every scan. New matches appear as open findings, and P0 resolves findings automatically once a grant no longer matches the query.

From the results, you can assign, ignore, or review fixes for findings ([Finding details](/posture/finding-details.md)), and route them to your [Tracker integrations](/integrations/tracker-integrations.md).

## Troubleshooting

| Problem                                    | Cause                                               | Fix                                                                                                                                                                  |
| ------------------------------------------ | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The monitor returns no findings            | The query is too narrow, or no current data matches | Re-run the query on the Inventory page and confirm it returns the expected results before saving                                                                     |
| The monitor returns too many findings      | The query is too broad                              | Add type, attribute, or via matches ([Query search](/inventory/query-search.md)) to narrow scope, for example, scope to one provider with `entitlement:provider:aws` |
| The monitor isn't in the Posture list      | Findings appear after the next scan completes       | Wait for the next scan, or trigger a scan from the environment settings ([Settings](/settings/settings.md))                                                          |
| Results changed unexpectedly between scans | The underlying access data changed                  | Open a finding and review its **Attack Path** and **Details** to see why it now matches                                                                              |

## What's next

* Tune detection with the full [Search reference](/inventory/query-search/search-reference.md).
* Analyze and resolve the findings the monitor produces. See [Finding details](/posture/finding-details.md).
* Connect a tracker integration ([Tracker integrations](/integrations/tracker-integrations.md)) to assign findings automatically.
