> 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/inventory/query-search/search-reference.md).

# Search Reference

This page is the complete reference for inventory queries: every query operator, search term, attribute, and allowed value. If you're new to the query language, read [Query Language Basics](/inventory/query-search/query-language-basics.md) first for a guided introduction — this page is for looking up specifics.

## Query operators

Query expressions let you be more specific in your searches. Here's a summary of every operator:

<table><thead><tr><th width="272.3333333333333">Expression</th><th width="218">See</th><th></th></tr></thead><tbody><tr><td>Key terms</td><td></td><td></td></tr><tr><td><code>keyword</code></td><td><a data-mention href="#contains-matches">#contains-matches</a></td><td>Match data substring</td></tr><tr><td><code>"keyword"</code></td><td><a data-mention href="#exact-matches">#exact-matches</a></td><td>Match data exactly</td></tr><tr><td><code>/keyword/</code></td><td><a data-mention href="#regex-matches">#regex-matches</a></td><td>Match data by regular expression</td></tr><tr><td><code>!keyword</code></td><td><a data-mention href="#inverted-matches">#inverted-matches</a></td><td>Invert keyword matches</td></tr><tr><td>Node terms</td><td></td><td></td></tr><tr><td><code>type:keyterm</code></td><td><a data-mention href="#type-matches">#type-matches</a></td><td>Match data types</td></tr><tr><td><code>type=keyterm</code></td><td><a data-mention href="#first-matches">#first-matches</a></td><td>Match first datum only</td></tr><tr><td><code>type:attribute:keyterm</code> or <code>type:{attribute1:keyterm1 attribute2:keyterm2 ...}</code></td><td><a data-mention href="#attribute-matches">#attribute-matches</a></td><td>Match data attributes</td></tr><tr><td>Path terms</td><td></td><td></td></tr><tr><td><code>keyterm->childpath</code></td><td>Child paths</td><td>Match a directed path in child direction</td></tr><tr><td><code>keyterm&#x3C;-parentpath</code></td><td>Parent paths</td><td>Match a directed path in parent direction</td></tr><tr><td><code>keyterm&#x3C;>eitherpath</code></td><td>Either paths</td><td>Match a directed path in either parent or child direction</td></tr><tr><td><code>childpath</code> | <code>parentpath</code> | <code>eitherpath</code></td><td><a data-mention href="#via-matches">#via-matches</a></td><td>Place multiple conditions on a data connection</td></tr><tr><td>Exclusion term</td><td></td><td></td></tr><tr><td><code>^pathterm</code></td><td><a data-mention href="#exclusion-matches">#exclusion-matches</a></td><td>Remove matches from results</td></tr><tr><td>Compound expression</td><td></td><td></td></tr><tr><td><code>expression term</code></td><td><a data-mention href="#multiple-matches">#multiple-matches</a></td><td>Require multiple data connections</td></tr></tbody></table>

*Cypher equivalents*

Each detailed explanation below also describes the equivalent statement in the Cypher query language (replace `{show}` with the corresponding label of the "show" control).

When displaying data as a table, the displayed data are the nodes matching the "show" type (represented by `s` in the equivalent queries); when displaying data as a graph visualization, the displayed data are the returned paths (represented by `p` in the equivalent queries).

### "Contains" matches

In its simplest usage, P0 matches IAM data if it includes your search keyword. For example, searching for `compute` shows you grants that allow access to any compute resource, give any privileges with "compute" in their name, grant a permission set with "compute" in its name, or grant access to compute service principals.

"Contains" matches are case insensitive; use [#exact-matches](#exact-matches "mention") to find data with exact casing.

*Cypher equivalent*:

```cypher
CALL () {
    MATCH p=(s:{show})-[*]->(r)
    RETURN p, r, s
    UNION
    MATCH p=(r)-[*]->(s:{show})
    RETURN p, r, s
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE r[k] =~ '(?i).*{keyword}.*')
RETURN p, s
```

### Exact matches

To match data exactly, enclose your keyword in double quotes. For example, searching for `compute.instances.get` in GCP matches extra permissions, such as `compute.instances.getEffectiveFirewalls`. Searching for `"compute.instances.get"` limits results to only those grants that have that specific permission.

{% hint style="info" %}
When using exact matches with type and attribute matches, the quotes surround the keyword only: `type:attribute:"keyword"`.

You can also use quotes to search for data where the data includes a colon without triggering a type or attribute match. For example, `risk:"exfiltration:data"` returns all results that yield a data exfiltration risk.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE r[k] = '{keyword}')
RETURN p, s
```

### Regex matches

To match data against a regular expression, enclose your pattern in forward slashes. For example, `/^arn:aws:iam::\d+:role\//` matches values that start with an AWS IAM role ARN prefix, and `/prod|staging/` matches values containing either `prod` or `staging`.

P0 evaluates the pattern with the standard JavaScript regular expression engine, so anchors (`^`, `$`), character classes, quantifiers, and alternation (`|`) all work as you'd expect.

Regex matches combine with type and attribute matches the same way other keywords do — the slashes surround the pattern only: `type:/pattern/` or `type:attribute:/pattern/`. To invert a regex match, place the `!` before the pattern: `type:attribute:!/pattern/`. See [#inverted-matches](#inverted-matches "mention").

{% hint style="warning" %}
Regex matches are **case sensitive**, unlike [#contains-matches](#contains-matches "mention"), which are case insensitive. JavaScript inline flags such as `/pattern/i` aren't supported, so express case insensitivity inside the pattern — for example, `/[Pp]rod/`.
{% endhint %}

{% hint style="info" %}
To match a literal forward slash inside the pattern, escape it as `\/` — for example, `/role\/Admin/`. An empty pattern (`//`), an unclosed pattern (`/abc`), or a syntactically invalid pattern is rejected. P0 also rejects patterns that are vulnerable to [ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) (catastrophic backtracking), such as `/(a+)+$/`; simplify the pattern if you hit this.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE r[k] =~ '{keyword}')
RETURN p, s
```

### Inverted matches

You can search for grants and principals that are connected to data that *don't* match a keyword by typing a `!` in front of your search keyword.

Note that using an inverted match on its own usually doesn't do much, as grants and principals connect to *many* data, and some of these data are likely to not match your keyword. Instead, inverted matches are usually best when combined with type or attribute matches, or with exclusion matches. For example, `principal:mfa:!enabled` shows you all users that have either disabled or unknown MFA status.

{% hint style="info" %}
When using inverted matches with type and attribute matches, the `!` comes *after* the type and attribute: `type:attribute:!keyword`.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE NOT ({keyterm condition}))
RETURN p, s
```

### Exclusion matches

You can search for items that aren't connected to data that match a term by typing a `^` in front of your entire search term.

For example, searching for `^usage:type:"unused"` shows all grants that have only used or unknown permission usage. Searching for `^usage:type:!"unused"` shows all grants where *all* permissions are unused.

{% hint style="info" %}
When using exclusion matches, the `^` comes *before* the type and attribute: `^type:attribute:keyterm`.
{% endhint %}

*Cypher equivalent*:

```cypher
MATCH (s1:{show})
WHERE (COUNT {
    // pathterm query w/out "RETURN"
    AND s=s1
}) = 0
RETURN s1
```

### Type matches

Limit your search to a specific type of IAM data using a type prefix. For example, adding `risk:CRITICAL` in front of your search limits your search to only showing grants that allow a critical IAM risk (as defined by the [IAM Privilege Catalog](https://catalog.p0.dev/scores)). See [#search-types](#search-types "mention") for a list of all possible types.

{% hint style="info" %}
You can use a type match without a keyword to search for the presence of data.

For example, `condition:` shows you all conditional grants.
{% endhint %}

*Cypher equivalent*:

<pre class="language-cypher"><code class="lang-cypher"><strong>CALL () {
</strong>    // per "contains" CALL statement
}
WITH p, r, s
WHERE r:{type} AND ANY(k IN keys(r) WHERE r[k] =~ '(?i).*{keyword}.*')
RETURN p, s
</code></pre>

### "First" matches

Data may connect to a chain of items of the same type. For instance, a grant on a resource gives access to all that resource's children, and all those child resources' children, and so forth. Or, grants may target directory groups with nested group membership.

To restrict your search to only the first item in such a chain, use a first match. For example, `principal=alice@my.co` shows only the `alice@my.co` user, and not the groups to which that user belongs.

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE NOT (p)-[*]->(:{type})-[*]->(r)
  AND NOT (r)-[*]->(:{type})-[*]->(p)
  AND ANY(k IN keys(r) WHERE r[k] =~ '(?i).*{keyword}.*')
RETURN p, s
```

### Attribute matches

Attribute expressions allow you to make even more specific searches. For example, searching for `credential:last90:unused` limits displayed principals to those with at least one credential that hasn't been used in the previous 90 days. See [#search-attributes](#search-attributes "mention") for a list of all possible attributes.

{% hint style="info" %}
You can combine first and attribute matches using the syntax `{type}={attribute}:{keyterm}`.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE r:{type} AND r.{attribute} =~ '(?i).*{keyword}.*'
RETURN p, s
```

### Multiple matches

Return items that connect to multiple data by separating search terms using whitespace.

For instance, `resource:one resource:two` shows you grants that give access to both resources "one" and "two".

*Cypher equivalent*:

```cypher
CALL () {
    // Result of first query
    RETURN p AS p1, s AS s1
}
WITH p1, s1
CALL () {
    // Result of second query
    RETURN p AS p2, s AS s2
}
WITH p2, s2
WHERE s1 = s2
RETURN s1, p1, p2
```

### Via matches

Your IAM data are modeled as a directed graph. You can require data to connect to your search results according to multiple search terms using a via match.

To use a via match, connect two or more terms using `->` (for child relationships), `<-` (for parent relationships), or `<>` (for either child or parent relationships).

For example, to find all entitlements that have unused permissions that create a data exfiltration risk, you can search for `usage:type:"unused"->risk:"exfiltration:data"`.

You can chain multiple terms together using more `->`. For example `usage:type:"unused"->privilege:s3->risk:"exfiltration:data"`.

{% hint style="warning" %}
Paths must consistently use child, parent, or "either" relationship syntax. Mixed paths like `a->b<-c` are not currently supported.
{% endhint %}

You can reference how data are connected in this graph using [#iam-graph](#iam-graph "mention").

{% hint style="info" %}
Exclusion matches combined with via matches return results where one or more of the via conditions don't match.
{% endhint %}

*Cypher equivalent for* `s<>r`:

```cypher
CALL () {
    MATCH p=(s:{show})-[*]->(q)-[*]->(r)
    RETURN p, q, r, s
    UNION
    MATCH p=(r)-[*]->(q)-[*]->(s:{show})
    RETURN p, q, r, s
}
WITH p, q, r, s
WHERE
    // constraints on q
    AND
    // constraints on r
RETURN p, s
```

## Search types

These are all the possible search types, and their meaning:

* **awsPolicy** - an AWS policy
* **condition** - a grant condition
* **consumer** - the entity that authenticates using a credential; this is typically an IP address
* **credential** - a single authentication credential; search matches the name of the credential (e.g. ID of an API key); will be "federated" if the principal authenticates using SSO
* **entitlement** - a set of privileges to use one or more resources, granted to an identity (an entitlement may be an AWS policy assignment, GCP role binding, or Azure / Kubernetes / Okta / Workspace role assignment)
* **identity** - an IAM identity; search matches the name of the identity (e.g. email; group name, AWS role name, etc.)
* **lateral** - represents potential machine-identity impersonation; each path is represented by two graph nodes, one attached to the grant that allows impersonation, the other attached to the principal that can be impersonated (see `lateral:flow` below)
* **permissionSet** - an AWS permission set
* **privilege** - a grantable privilege (this can be an AWS action, or Azure, Google Cloud, Okta, or Workspace permission)
* **resource** - an IAM resource
* **risk** - a security risk associated with holding a privilege; possible risks are listed in the [IAM Privilege Catalog](https://catalog.p0.dev/risks); you can also search for risk severity scores (e.g. `CRITICAL`)
* **role** - an Azure, Google Cloud, Kubernetes, Okta, or Workspace role (note that this is *not* an AWS role; use `identity:type:aws-iam-role` to search AWS roles)
* **usage** - represents privilege usage (in the last 90 days):
  * `used` - the privilege was used in the last 90 days
  * `unused` - the privilege has been unused for all of the previous 90 days
  * `unknown` - P0 lacks evidence to determine if the privilege is used or unused

## Search attributes

Search attributes allow more specific type searches. Allowable attributes are:

{% hint style="info" %}
Microsoft Entra data uses two provider values: `entra-id` for the current Microsoft Entra ID integration and `azure-ad` for the legacy Azure AD integration. Search the value that matches your installed integration. Azure cloud resources (subscriptions, role assignments) use the separate `azure` provider.
{% endhint %}

* **condition:expression** - a grant condition's expression
* **credential:created90** - represents if this credential was created within the previous 90 days (`fresh`) or prior (`stale`)
* **credential:last40** & **credential:last90** - represents if this authentication method has been used in the previous 40 or 90 days (respectively); values are `used` or `unused`
* **credential:type** - the type of the authentication credential; may be one of
  * `federated` - a credential from an external IAM system
  * `key` - a static secret credential
  * `password` - a user password credential (for example, a Microsoft Entra ID user password)
  * `short-lived` - represents all ephemeral credentials, including JWTs, temporary keys, account impersonation, and the like
* **entitlement:cross** - true if access is granted to an identity managed outside of the IAM resource (e.g. a GCP role assigned to an Okta user)
* **entitlement:parent** - the scope (AWS account, Azure subscription, GCP project, etc.) in which this entitlement is defined
* **entitlement:principal** - the principal identity granted access by this entitlement
* **entitlement:principalType** - the identity type of this entitlement's principal identity (see `identity:type` below for possible values)
* **entitlement:provider** - the service in which this entitlement is defined; possible values are `aws`, `azure`, `azure-ad`, `entra-id`, `gcp`, `k8s`, `okta`, or `workspace`
* **entitlement:resource** - the resource(s) to which this entitlement grants access
* **entitlement:role** - the role granted by this entitlement
* **identity:accessAdd** - who can add users to this group (only available for Workspace groups):
  * `admin` - only group administrators can add users
  * `group` - anyone in the group can add users
  * `owner` - only the group owners can add users
  * If not present, no one can directly add users
* **identity:accessApprove** - who can approve group join requests (only available for Workspace groups):
  * `admin` - only group administrators can approve requests
  * `group` - anyone in the group can approve requests
  * `owner` - only the group owners can approve requests
  * If not present, no one can approve requests
* **identity:accessJoin** - who can join this group without approval (only available for Workspace groups):
  * `public` - anyone on the Internet can join
  * `domain` - anyone in the Workspace domain can join
  * `invited` - users can join if they've received an invite
  * If not present, users can only be directly added to the group
* **identity:accessView** - who can view this group's content (only available for Workspace groups; content is the group's messages):
  * `public` - anyone on the Internet can view
  * `domain` - anyone in the Workspace domain can view
  * `group` - anyone in the group can view
  * `admin` - only group administrators can view
* **identity:external** - true if the identity is managed outside the assessed environment
* **identity:parent** - the scope (AWS account, Azure subscription, GCP project, etc.) that manages this identity
* **identity:provider** - the service that manages this identity; possible values are `aws`, `azure`, `azure-ad`, `entra-id`, `gcp`, `k8s`, `okta`, or `workspace`
* **identity:status** - one of:
  * `enabled` - the principal can authenticate
  * `disabled` - the principal's authentication is disabled
* **identity:type** - the type of the IAM principal; may be one of
  * `aws-iam-role` - an AWS IAM role
  * `aws-permission-set-role` - an AWS IAM role automatically generated by AWS when assigning an AWS permission set to an account
  * `entra-app-registration` - a Microsoft Entra ID application registration (the application object that defines an app and its permissions)
  * `federated` - an identity used to provide access to identities from another provider (e.g. an AWS IAM role with `Principal.Federated` in its trust relationship); the identity's parents will be the federated identities
  * `group` - a directory group
  * `public` - any identity
  * `service-agent` - a provider-managed account
  * `service-account` - a machine identity (in AWS this is usually an AWS role)
  * `service-principal` - a Microsoft Entra ID service principal (the local instance of an application or managed identity within a tenant)
  * `user` - a user identity
* **lateral:type** - the mechanism via which lateral escalation can be achieved:
  * `grant` - lateral movement via a granted privilege (e.g. GCP `iam.serviceAccounts.actAs` or AWS `sts:assumeRole`)
  * `resource` - lateral movement via usage of a service-linked resource (e.g. lateral movement to a compute service identity via shell access)
  * Note: federated access is represented as a direct principal-to-principal relationship, and is not modeled via lateral-movement
* **privilegeSet:provider** - the service that manages this role or AWS policy; possible values are `aws`, `azure`, `azure-ad`, `entra-id`, `gcp`, `k8s`, `okta`, or `workspace`
* **resource:service** - the resource's parent cloud service; use the API path of the service (e.g. `sso` instead of `Identity Center`)
* **resource:type** - the resource's type (e.g. `bucket`)
* **risk:score** - the access risk score from the [IAM Privilege Catalog](https://catalog.p0.dev/risks); one of `CRITICAL`, `HIGH`, `MEDIUM`, `BOOST`, `EVASION`, or `LOW`

## IAM graph

Your IAM data are connected in a directed graph, as shown, with each node label indicating the datum's respective type:

<div data-full-width="true"><figure><img src="/files/eaDEI372kpVB57bLgdPt" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Via queries should only be used for types matching along a directed path in this graph. E.g., `principal:->used:->risk:` will produce matches, but `resource:->risk:` will not.
{% endhint %}

## Query builder

You can assemble a single search term with the **Query builder** instead of typing it. Click the **+** button beside the **where** box, above the table or graph, to open the builder form. As you set each control, the builder shows a live preview of the term, and clicking **Add term** inserts it into the **where** box.

Each control maps to an operator described above:

| Builder control                                   | Effect on the term                                                                   |
| ------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **Show … that are** vs **can reach**              | Matches the displayed node itself (`=`) or a node it reaches (`:`).                  |
| Search type (**identities**, **entitlements**, …) | Adds the [type prefix](#type-matches), such as `identity:`.                          |
| **with** *(attribute)*                            | Adds an [attribute filter](#attribute-matches).                                      |
| **containing** vs **equal to**                    | [Substring match](#contains-matches) or [exact match](#exact-matches) (`"keyword"`). |
| **Invert match?**                                 | Applies the `!` [inverted](#inverted-matches) operator to the keyword.               |
| **Remove match?**                                 | Applies the `^` [exclusion](#exclusion-matches) operator to the term.                |
| **Only first node?**                              | Uses `=` instead of `:` to match only the [first node](#first-matches) in a chain.   |

The builder constructs one term at a time and produces ordinary query text — identical to what you would type by hand. To require several conditions, add multiple terms (see [Multiple matches](#multiple-matches)).


---

# 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.p0.dev/inventory/query-search/search-reference.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.
