# Detectors

Detectors are conditions matched against requests, responses, or (on WebApp) the rendered page. They appear in the `detect:` block of every rule, and in the `trigger:` block of an API `transform:` or `extractors:` entry.

Both surfaces share the matcher grammar (`is`, `is_not`, `in`, `contains`, `regex`, `gt`, `lt`, `jq`, ...) but expose different `if:` keys: API rules inspect HTTP-level data, WebApp rules inspect the browser state.

## Detectors Available on API

### Scan Type Detector

`if: scan.type`

Match against the type of scan being performed.

**Matcher Type:** `ScanTypeMatcher` · **Operators:** `is`, `is_not`, `in` · **Valid values:** `REST`, `GRAPHQL`

```yaml
detect:
  - if: scan.type
    is: REST

# OR
detect:
  - if: scan.type
    in: [REST, GRAPHQL]
```

#### Properties

- `is`: The scan type is exactly this
- `is_not`: The scan type isn't this type
- `in`: The scan type is in this list

---

### CRUD Detector

`if: helpers.request.crud`

Use this to select against the detected CRUD operation of the request.

#### Example

```yaml
detect:
  - if: helpers.request.crud
    in:
      - CREATE
      - UPDATE
```

#### Properties

- `is`: Condition is the request is this CRUD operation
- `is_not`: Condition is the request isn't this CRUD operation
- `in`: Condition is the request is in this list of CRUD operations (exact match)

---

### Response Status Detector

`if: response.status_code`

Match against the HTTP response status code.

**Matcher type:** `IntegerMatcher` · **Operators:** `is`, `is_not`, `gt`, `lt`, `in`

```yaml
detect:
  - if: response.status_code
    in: [200, 206]
```

For simple success/failure checks prefer `helpers.response.is_successful` (it covers the full 2xx range and is more readable).

In context: partial-content trick for SQL dump probing:

#### Exposed SQL Dumps Reachable Over HTTP

Probe a curated list of common SQL dump filenames at the root of the target and alert if the server returns the file with a SQL DDL/DML signature in the body.

Backups left in the web root are one of the highest-impact and cheapest-to-find exposures in API testing. This rule probes a curated list of common backup filenames (`backup.sql`, `dump.sql`, `db.sql`, `mysqldump.sql`, ...) using a `Range: bytes=0-3000` header so the download stays small even if the file is multi-gigabyte. Extend the `seed:` list with additional paths to suit your target.

Detection requires both a 200/206 status and a body containing typical SQL DDL/DML keywords (`DROP TABLE`, `CREATE TABLE`, `INSERT INTO`, `LOCK TABLE`). The status code and body regex are AND-combined so a generic 200 page with no SQL content doesn't fire.

**When to use:** Run against every public host. Especially useful immediately after deployments, when build artifacts are sometimes left in `/public` by accident.

**OWASP:** A05:2021 Security Misconfiguration · **CWE:** [CWE-540](<https://cwe.mitre.org/data/definitions/540.html>)

**Severity rationale:** HIGH: exposed dumps regularly contain credentials, password hashes, and full PII.

**Features used:** `seed`, `detect`, `rest seeder with custom Range header`, `response.body.text regex`, `response.status_code in`

```yaml
rule:
  id: example-api-exposed-sql-dumps
  type: API
  alert:
    name: Exposed SQL dump
    context: |
      A request to a common SQL dump filename returned a 200/206 with
      DDL/DML keywords in the body, indicating a database backup
      reachable over HTTP.
    severity: HIGH
    category: INFORMATION_DISCLOSURE
  seed:
  - protocol: rest
    method: GET
    path: /backup.sql
    headers:
      Range: bytes=0-3000
  - protocol: rest
    method: GET
    path: /database.sql
    headers:
      Range: bytes=0-3000
  - protocol: rest
    method: GET
    path: /dump.sql
    headers:
      Range: bytes=0-3000
  - protocol: rest
    method: GET
    path: /db.sql
    headers:
      Range: bytes=0-3000
  - protocol: rest
    method: GET
    path: /mysqldump.sql
    headers:
      Range: bytes=0-3000
  - protocol: rest
    method: GET
    path: /db_backup.sql
    headers:
      Range: bytes=0-3000
  - protocol: rest
    method: GET
    path: /wp-content/uploads/dump.sql
    headers:
      Range: bytes=0-3000
  detect:
  - if: response.body.text
    regex: .*((DROP|CREATE|(?:UN)?LOCK) TABLE|INSERT INTO).*
  - if: response.status_code
    in:
    - 200
    - 206
```

**References:**

- [https://owasp.org/Top10/A05\_2021-Security\_Misconfiguration/](<https://owasp.org/Top10/A05_2021-Security_Misconfiguration/>)
- [https://cwe.mitre.org/data/definitions/540.html](<https://cwe.mitre.org/data/definitions/540.html>)

#### Properties

- `is`: Condition is this exact integer
- `is_not`: Condition isn't this exact integer
- `in`: Condition is in this list of integers (exact match)
- `gt`: Condition is greater than this integer
- `lt`: Condition is less than this integer

---

### Response Duration Detector

`if: response.duration_ms`

Use this to compare the duration of the request in milliseconds.

#### Example

```yaml
detect:
  - if: response.duration_ms
    gt: 200
```

#### Properties

- `is`: Condition is this exact integer
- `is_not`: Condition isn't this exact integer
- `in`: Condition is in this list of integers (exact match)
- `gt`: Condition is greater than this integer
- `lt`: Condition is less than this integer

---

### Schema Authentication Detector

`if: schema.need_authentication`

Use this to select whether or not the schema requires authentication.

#### Example

```yaml
detect:
  - if: schema.need_authentication
    is: false
```

#### Properties

- `is`: Condition is true
- `is_not`: Condition is false

---

### Request Authentication Detector

`if: request.is_authenticated`

Use this to select whether the request is authenticated.

#### Example

```yaml
detect:
  - if: request.is_authenticated
    is: true
```

#### Properties

- `is`: Condition is true
- `is_not`: Condition is false

---

### Schema Path Reference Detector

`if: schema.path_ref`

Match the operation name (GraphQL) or the path (REST) of the request.

**Matcher type:** `StringMatcher` · **Operators:** `is`, `is_not`, `contains`, `regex`, `in`

```yaml
detect:
  - if: schema.path_ref
    contains: /admin/

# Or regex over a versioned path:
detect:
  - if: schema.path_ref
    regex: /api/v[0-9]+/admin/.*
```

In context: anonymous admin route detection:

#### Anonymous Request to /Admin Succeeded

Flag any successful response on a path containing `/admin/` issued without authentication: the cheapest deterministic check for an accidentally-public administrative surface.

Almost no application intentionally exposes admin functionality to anonymous callers. When an endpoint matching `/admin/` returns a 2xx to a public request, the most likely explanations are:

- missing authentication middleware,
- a route that bypasses the global auth filter,
- a debug / staging route accidentally promoted to production.

The rule combines three signals (`schema.path_ref` contains `/admin`, request is unauthenticated, response is successful) so it fires only when all three hold.

**When to use:** Any HTTP API. Equally useful as a regression test in CI and as a routine production scan rule. Tighten `contains: /admin` to a more specific path if your product legitimately exposes anonymous admin metadata pages.

**OWASP:** API5:2023 Broken Function Level Authorization · **CWE:** [CWE-862](<https://cwe.mitre.org/data/definitions/862.html>)

**Severity rationale:** HIGH: anonymous admin access is reliably exploitable and one of the most common high-severity misconfigurations in real-world API security reports.

**Features used:** `detect`, `schema.path_ref`, `request.is_authenticated`, `helpers.response.is_successful`

```yaml
rule:
  id: example-api-public-admin-route
  type: API
  alert:
    name: Public administrative route
    context: |
      An unauthenticated request to a path containing `/admin/`
      returned a 2xx response. The route is missing an authentication
      check.
    severity: HIGH
    category: ACCESS_CONTROL
  detect:
  - if: schema.path_ref
    contains: /admin/
  - if: request.is_authenticated
    is: false
  - if: helpers.response.is_successful
    is: true
```

**References:**

- [https://owasp.org/API-Security/editions/2023/en/0xa5-broken-function-level-authorization/](<https://owasp.org/API-Security/editions/2023/en/0xa5-broken-function-level-authorization/>)
- [https://cwe.mitre.org/data/definitions/862.html](<https://cwe.mitre.org/data/definitions/862.html>)

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---

### Response Success Detector

`if: helpers.response.is_successful`

True when the response status code is in the 2xx range.

**Matcher type:** `BooleanMatcher` · **Operators:** `is`

```yaml
detect:
  - if: helpers.response.is_successful
    is: true
```

In context: combine with `helpers.request.crud` and `request.is_authenticated` to flag anonymous mutations:

#### Unauthenticated Mutation Succeeded

Detect any successful CREATE / UPDATE / DELETE issued without an authenticated user.

Most APIs gate state-changing operations behind authentication. When a public (unauthenticated) request manages to perform a CREATE / UPDATE / DELETE and receives a 2xx response, the endpoint is missing an authn or authz check.

The rule combines three deterministic signals: the inferred CRUD operation isn't READ, the request was issued by the `public` pseudo-user (Escape's representation of an anonymous caller), and the response is in the 2xx range.

**When to use:** Apply on every API. This is one of the highest-signal rules in the library and rarely produces false positives because all three conditions must hold simultaneously.

**OWASP:** API2:2023 Broken Authentication · **CWE:** [CWE-306](<https://cwe.mitre.org/data/definitions/306.html>)

**Severity rationale:** HIGH: anonymous mutations typically allow unauthorized data writes, deletion of resources, or trivial denial-of-service via mass creation.

**Features used:** `detect`, `helpers.request.crud`, `request.is_authenticated`, `helpers.response.is_successful`

```yaml
rule:
  id: example-api-unauthenticated-mutation
  type: API
  alert:
    name: Unauthenticated mutation succeeded
    context: |
      A CREATE / UPDATE / DELETE request issued without authentication
      returned a 2xx response. The endpoint is missing an authentication
      or authorization check.
    severity: HIGH
    category: ACCESS_CONTROL
  detect:
  - if: helpers.request.crud
    is_not: READ
  - if: request.is_authenticated
    is: false
  - if: helpers.response.is_successful
    is: true
```

**References:**

- [https://owasp.org/API-Security/editions/2023/en/0xa2-broken-authentication/](<https://owasp.org/API-Security/editions/2023/en/0xa2-broken-authentication/>)
- [https://cwe.mitre.org/data/definitions/306.html](<https://cwe.mitre.org/data/definitions/306.html>)

#### Properties

- `is`: Condition is true
- `is_not`: Condition is false

---

### Schema URL Detector

`if: schema.url`

Use this to string compare the URL of the request.

#### Example

```yaml
detect:
  - if: schema.url
    regex: .*(internal|private).*
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---

### Request User Detector

`if: request.user`

Match the user name attached to the request. The value must match a user defined in your scan authentication settings (the special user `public` represents an unauthenticated caller).

**Matcher type:** `StringMatcher` · **Operators:** `is`, `is_not`, `contains`, `regex`, `in`

```yaml
detect:
  - if: request.user
    is: tester@example.com
```

In context: BOLA detection by replaying as a different user:

#### BOLA Via User Swap with Fingerprint Comparison

Replay every successful authenticated request as a different user and flag responses that succeed AND return the same body fingerprint: classic Broken Object Level Authorization.

Broken Object Level Authorization (BOLA / IDOR) is the [\#1](<https://github.com/icarossio/escape-technologies/issues/1> "GitHub Issue: icarossio/escape-technologies #1") API risk in the OWASP API Top 10. The pattern is straightforward: endpoint `X` correctly authenticates `tester@example.com` and returns its own data, but never re-checks ownership when a different user calls the same URL: so `attacker@example.com` gets the same response.

This rule encodes the test deterministically:

1. `transform.trigger` selects every successful request issued by `tester@example.com`.
2. `transform.mutate` re-issues that request with `request.user` set to `attacker@example.com`.
3. `detect` fires when the replayed response is also successful AND its body fingerprint matches the original: meaning the API returned the first user's data to the second user.

**When to use:** Any REST or GraphQL endpoint that returns user-scoped data. Pair with your authentication configuration in the Escape platform: define at least two users with disjoint resources for the fingerprint check to be meaningful.

**OWASP:** API1:2023 BOLA · **CWE:** [CWE-639](<https://cwe.mitre.org/data/definitions/639.html>)

**Severity rationale:** HIGH: cross-tenant data leakage is typically a reportable security incident and a frequent cause of GDPR / SOC 2 findings.

**Features used:** `transform`, `detect`, `request.user mutator`, `helpers.fingerprints.same`, `helpers.response.is_successful`

```yaml
rule:
  id: example-api-bola-user-swap-fingerprint
  type: API
  alert:
    name: Possible BOLA via user swap
    context: |
      A successful authenticated response was returned with an identical
      body fingerprint when the same request was replayed as a different
      user. The endpoint is likely missing an object-level authorization
      check.
    severity: HIGH
    category: ACCESS_CONTROL
  transform:
    trigger:
    - if: helpers.response.is_successful
      is: true
    - if: request.user
      is: tester@example.com
    mutate:
    - key: request.user
      value: attacker@example.com
  detect:
  - if: helpers.response.is_successful
    is: true
  - if: helpers.fingerprints.same
    is: true
```

**References:**

- [https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/](<https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/>)
- [https://cwe.mitre.org/data/definitions/639.html](<https://cwe.mitre.org/data/definitions/639.html>)

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---

### Method Detector

`if: request.method`

Use this to select against the request HTTP Method.

#### Example

```yaml
detect:
  - if: request.method
    is: OPTIONS
```

#### Properties

- `is`: Condition is the request is this CRUD operation
- `is_not`: Condition is the request isn't this CRUD operation
- `in`: Condition is the request is in this list of CRUD operations (exact match)

---

### Variable Defined Detector

`if: variable.defined`

Use this to detect if a given variable has been extracted or not yet.

#### Basic Example

```yaml
detect:
  - if: variable.defined
    variable_name: user_id
```

#### Common Use Cases

- Making sure a variable has been already extracted before executing a mutation, a detector or another extraction.

#### Properties

- `variable_name`: Use this to specify the variable name that has to be defined before proceeding further

---

### Request Headers Detector

`if: request.headers`

Use that to select and compare the request headers in a key value dictionary.

#### Example

```yaml
detect:
  - if: request.headers
    key:
      is: 'X-OPERATION'
    value:
      is: 'PAY'
```

#### Properties

- `key`: Key to match
- `value`: Value to match

---

### Response Headers Detector

`if: response.headers`

Use that to select and compare the response headers in a key value dictionary.

#### Example

```yaml
detect:
  - if: response.headers
    key:
      is: 'X-RESULT'
    value:
      is: 'PAID'
```

#### Properties

- `key`: Key to match
- `value`: Value to match

---

### Response Body JSON Detector

`if: response.body.json`

Use this to select and compare the response body when detected as JSON, using jq-like syntax.

#### Example 1

```yaml
detect:
  - if: response.body.json
    is:
      id: 42
```

#### Example 2

```yaml
detect:
  - if: response.body.json
    jq: '.role == admin'
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this exact JSON
- `is_not`: Condition isn't this exact JSON
- `in`: Condition is in this list of JSON
- `jq`: JQ query to match and use as boolean. If `use_extraction` is True, only this attribute will be parsed (if set).

---

### Request Body JSON Detector

`if: request.body.json`

Use this to select and compare the request body when detected as JSON, using jq-like syntax.

#### Example 1

```yaml
detect:
  - if: request.body.json
    is:
      id: 42
```

#### Example 2

```yaml
detect:
  - if: request.body.json
    jq: '.role == admin'
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this exact JSON
- `is_not`: Condition isn't this exact JSON
- `in`: Condition is in this list of JSON
- `jq`: JQ query to match and use as boolean. If `use_extraction` is True, only this attribute will be parsed (if set).

---

### Response Body Text Detector

`if: response.body.text`

Use this to select and compare the response body as text, using string compare.

#### Example

```yaml
detect:
  - if: request.body.text
    is_not: 'unauthorized'
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---

### Request Body Text Detector

`if: request.body.text`

Use this to select and compare the request body as text, using string compare.

#### Example

```yaml
detect:
  - if: request.body.text
    contains: 'password='
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---

### Request Object Detector

`if: request.object`

Use this to select and compare the detected object scalars (including custom scalars) in the request, with their kind, name and value.

#### Example

```yaml
detect:
  - if: request.object
    type:
      in:
        - email
        - phone
        - street_address
```

#### Properties

- `type`: Object scalar type to match
- `name`: Object scalar name to match
- `value`: Object scalar value to match

---

### Response Object Detector

`if: response.object`

Use this to select and compare the detected object scalars (including custom scalars) in the response, with their kind, name and value.

#### Example

```yaml
detect:
  - if: response.object
    type:
      in:
        - email
        - phone
        - street_address
```

#### Properties

- `type`: Object scalar type to match
- `name`: Object scalar name to match
- `value`: Object scalar value to match

---

### JSON Matches Count Detector

`if: helpers.json_matches.count`

Use this to count the number of times a JSON match is in the current and original response.

#### Properties

- `is`: Condition is this exact integer
- `is_not`: Condition isn't this exact integer
- `in`: Condition is in this list of integers (exact match)
- `gt`: Condition is greater than this integer
- `lt`: Condition is less than this integer
- `jq`: Use this to select the exact JSON you want to compare between the current and original response.

---

### Regex Matches Count Detector

`if: helpers.regex_matches.count`

Use this to count the number of times a regex match is in the current and original response.

#### Properties

- `is`: Condition is this exact integer
- `is_not`: Condition isn't this exact integer
- `in`: Condition is in this list of integers (exact match)
- `gt`: Condition is greater than this integer
- `lt`: Condition is less than this integer
- `regex`: Condition is matched on this regex with fullmatch

---

### Fingerprint Count Detector

`if: helpers.fingerprints.count`

Use this to select and compare the count of unique fingerprints of the current and original response.

#### Properties

- `is`: Condition is this exact integer
- `is_not`: Condition isn't this exact integer
- `in`: Condition is in this list of integers (exact match)
- `gt`: Condition is greater than this integer
- `lt`: Condition is less than this integer

---

### Fingerprint Equality Detector

`if: helpers.fingerprints.same`

Use this to determine whether the current and original responses have the same fingerprint.

#### Properties

- `is`: Condition is true
- `is_not`: Condition is false

---

### JSON Matches All Detector

`if: helpers.json_matches.all`

Use this to determine whether every the current and original responses contain the same JSON fragment.

#### Properties

- `is`: Condition is true
- `is_not`: Condition is false
- `jq`: Use this to select the exact JSON you want to compare between the current and original response.

---

### Regex Matches All Detector

`if: helpers.regex_matches.all`

Use this to determine whether every the current and original responses match the same regular expression.

#### Properties

- `is`: Condition is true
- `is_not`: Condition is false
- `regex`: Condition is matched on this regex with fullmatch

---

## Detectors Available on WebApp

### Last Request Response Text Detector

`if: last_request.response.text`

Use this to assert that the last request response text contains a specific substring.

#### Example

```yaml
detect:
  - if: last_request.response.text
    contains: 'Unauthorized'
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---

### JS Assertion Detector

`if: js_assertion`

Use this to execute a JavaScript command and assert it returns true.

#### Example

```yaml
detect:
  - if: js_assertion
    command: 'return window.isAuthenticated === false;'
```

#### Properties

- `command`: JavaScript command to execute

---

### Page Selector Detector

`if: page_selector`

Use this to assert that a selector exists in the DOM.

#### Example

```yaml
detect:
  - if: page_selector
    contains: '#my-element'
```

#### Properties

- `contains`: Contains this string

---

### Page Text Detector

`if: page_text`

Use this to assert that a text is present in the page.

#### Example

```yaml
detect:
  - if: page_text
    contains: 'Hello, world!'
```

#### Properties

- `contains`: Contains this string

---

### Page Status Code Detector

`if: page_status_code`

Use this to assert that the page status code is a specific value.

#### Example

```yaml
detect:
  - if: page_status_code
    is: 200
```

#### Properties

- `is`: Condition is this exact integer
- `is_not`: Condition isn't this exact integer
- `in`: Condition is in this list of integers (exact match)
- `gt`: Condition is greater than this integer
- `lt`: Condition is less than this integer

---

### Local Storage Detector

`if: local_storage`

Use this to assert that a key is present in the local storage.

#### Example

```yaml
detect:
  - if: local_storage
    key:
      is: 'my-key'
    value:
      contains: 'pattern'
```

#### Properties

- `key`: Key to match
- `value`: Value to match

---

### Session Storage Detector

`if: session_storage`

Use this to assert that a key is present in the session storage.

#### Example

```yaml
detect:
  - if: session_storage
    key:
      is: 'my-key'
    value:
      contains: 'pattern'
```

#### Properties

- `key`: Key to match
- `value`: Value to match

---

### Cookie Contains Detector

`if: cookie`

Use this to assert that a cookie is present in the browser.

#### Example

```yaml
detect:
  - if: cookie
    key:
      is: 'my-key'
    value:
      contains: 'pattern'
```

#### Properties

- `key`: Key to match
- `value`: Value to match

---

### Header Contains Detector

`if: header`

Use this to match the browser's `document.headers` value.

#### Example

```yaml
detect:
  - if: header
    key:
      is: 'my-key'
    value:
      contains: 'pattern'
```

#### Properties

- `key`: Key to match
- `value`: Value to match

---

### Dialog Message Detector

`if: dialog.message`

Use this to assert that a JavaScript dialog (`alert`, `confirm`, `prompt`) was triggered by the page and inspect its message. Useful for catching reflected XSS payloads that fire `alert()` once rendered.

#### Example

```yaml
detect:
  - if: dialog.message
    contains: 'XSS'
```

#### Properties

- `use_extraction`: If True, variable references between {{ }} will be replace with the extracted value (If exists). The string representation of the variable will be used without any extra-processing.
- `is`: Condition is this string (case-insensitive)
- `is_not`: Condition isn't this string (case-insensitive)
- `in`: Condition is in this list (case-insensitive)
- `contains`: Contains this substring (case-insensitive)
- `regex`: Condition is matched on this regex with fullmatch (case-insensitive)

---
