Custom Rules Reference¶
Auto-generated reference for the JSON Schema accepted by the Escape platform. Both surfaces are covered below.
Shared models (AlertModel, Compliance, CustomRuleID, ...) are
documented once in the API reference; the WebApp reference lists
only WebApp-specific models and links back to the API section for
shared definitions.
API reference¶
APICustomRule¶
Objects¶
APIExtractor¶
APILogicalAndDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
and* |
List[APILogicalAndDetector,APILogicalNotDetector,APILogicalOrDetector,FingerprintCountDetector,FingerprintsSameDetector,HelpersRequestCrudDetector,HelpersResponseIsSuccessfulDetector,JSONMatchesAllDetector,JSONMatchesCountDetector,RegexMatchesAllDetector,RegexMatchesCountDetector,RequestBodyJSONDetector,RequestBodyTextDetector,RequestHeadersDetector,RequestIsAuthenticatedDetector,RequestMethodDetector,RequestObjectDetector,RequestUserDetector,ResponseBodyJSONDetector,ResponseBodyTextDetector,ResponseDurationDetector,ResponseHeadersDetector,ResponseObjectDetector,ResponseStatusCodeDetector,ScanTypeDetector,SchemaNeedAuthenticationDetector,SchemaPathRefDetector,SchemaUrlDetector,VariableDefinedDetector] |
Logical and on a list of detectors | |
if* |
Const[and] |
and |
Use this to apply a logical and on a list of detectors.### Exampleyamldetect: - if: and and: - if: helpers.request.crud in: - CREATE - UPDATE - if: response.status_code is: 200 |
APILogicalNotDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[not] |
not |
Use this to apply a logical not on a detector.### Exampleyamldetect: - if: not not: if: response.status_code is: 200 |
not |
APILogicalAndDetector, APILogicalNotDetector, APILogicalOrDetector, FingerprintCountDetector, FingerprintsSameDetector, HelpersRequestCrudDetector, HelpersResponseIsSuccessfulDetector, JSONMatchesAllDetector, JSONMatchesCountDetector, RegexMatchesAllDetector, RegexMatchesCountDetector, RequestBodyJSONDetector, RequestBodyTextDetector, RequestHeadersDetector, RequestIsAuthenticatedDetector, RequestMethodDetector, RequestObjectDetector, RequestUserDetector, ResponseBodyJSONDetector, ResponseBodyTextDetector, ResponseDurationDetector, ResponseHeadersDetector, ResponseObjectDetector, ResponseStatusCodeDetector, ScanTypeDetector, SchemaNeedAuthenticationDetector, SchemaPathRefDetector, SchemaUrlDetector, VariableDefinedDetector | null |
Logical not of a detector |
APILogicalOrDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[or] |
or |
Use this to apply a logical or on a list of detectors.### Exampleyamldetect: - if: or or: - if: helpers.request.crud in: - CREATE - UPDATE - if: response.status_code is: 200 |
or* |
List[APILogicalAndDetector,APILogicalNotDetector,APILogicalOrDetector,FingerprintCountDetector,FingerprintsSameDetector,HelpersRequestCrudDetector,HelpersResponseIsSuccessfulDetector,JSONMatchesAllDetector,JSONMatchesCountDetector,RegexMatchesAllDetector,RegexMatchesCountDetector,RequestBodyJSONDetector,RequestBodyTextDetector,RequestHeadersDetector,RequestIsAuthenticatedDetector,RequestMethodDetector,RequestObjectDetector,RequestUserDetector,ResponseBodyJSONDetector,ResponseBodyTextDetector,ResponseDurationDetector,ResponseHeadersDetector,ResponseObjectDetector,ResponseStatusCodeDetector,ScanTypeDetector,SchemaNeedAuthenticationDetector,SchemaPathRefDetector,SchemaUrlDetector,VariableDefinedDetector] |
Logical or on a list of detectors |
AlertModel¶
| Property | Type | Default | Description |
|---|---|---|---|
category |
CustomRuleCategory | CUSTOM |
Category of the alert |
compliance |
Compliance | null |
Compliance standards violated by this alert |
context* |
string |
Context of the alert | |
description |
string |
null |
Description of the alert |
name* |
string |
Name of the alert | |
remediation |
string |
null |
Remediation of the alert |
severity* |
CustomRuleSeverity | Severity of the alert |
BaseStringMutate¶
| Property | Type | Default | Description |
|---|---|---|---|
regex_replace |
RegexReplace | null |
Regex replace pattern. |
use_extraction |
boolean |
false |
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. |
value |
string |
null |
The value to set. |
values |
List[string] |
null |
The values to set, generates multiple queries. |
Compliance¶
| Property | Type | Default | Description |
|---|---|---|---|
cra |
Literal[Annex I-1, Article-11] |
null |
|
cwe |
Literal[16, 20, 22, 78, 79, 89, 93, 94, 116, 119, 200, 209, 215, 264, 284, 285, 287, 295, 306, 307, 311, 319, 326, 330, 331, 346, 347, 352, 353, 354, 400, 444, 453, 489, 502, 522, 523, 524, 548, 551, 573, 601, 611, 614, 676, 704, 710, 730, 732, 758, 770, 829, 862, 863, 915, 918, 942, 943, 1029, 1195] |
null |
|
dora |
Literal[Article-6, Article-8, Article-9, Article-11] |
null |
|
fedramp |
Literal[AC-2, AC-3, AC-4, AC-6, AC-7, AC-14, AC-17, AC-22, CM-2, CM-3, IA-5, SA-11, SC-5, SC-7, SC-8, SC-12, SC-13, SC-17, SC-18, SC-20, SC-28, SI-2, SI-3, SI-4, SI-7, SI-10, SI-11] |
null |
|
gdpr |
Literal[Article-5, Article-25, Article-32, Article-33] |
null |
|
hipaa |
Literal[Standard-1, Standard-2, Standard-3, Standard-4, Standard-5] |
null |
|
hitrust_csf |
Literal[01.c, 01.f, 01.g] |
null |
|
iec62443 |
Literal[CR 2.1, CR 3.1, CR 4.1, CR 4.3, CR 5.2, CR 7.1, CR 7.6] |
null |
|
iso27001 |
Literal[A.9.1, A.9.4, A.10.1, A.12.1, A.12.2, A.12.3, A.12.6, A.12.7, A.13.1, A.14.1, A.14.2, A.17.1, A.18.1] |
null |
|
mitre_attack |
Literal[T1531, T1595, T1557, T1110, T1580, T1059, T1659, T1555, T1486, T1530, T1602, T1213, T1565, T1140, T1499, T1190, T1203, T1211, T1068, T1083, T1606, T1592, T1589, T1590, T1525, T1556, T1542, T1496, T1207, T1505, T1553, T1195, T1082, T1221, T1199, T1552, T1550, T1078, T1102, T1220] |
null |
|
nis2 |
Literal[Article-6, Article-21, Article-22, Article-23, Article-28, Article-29, Article-33] |
null |
|
nist |
Literal[SP800-40, SP800-41, SP800-44, SP800-52, SP800-53, SP800-63B, SP800-81-2, SP800-92, SP800-95, SP800-123, SP800-161, SP800-190, SP800-207] |
null |
|
owasp |
Literal[API1:2023, API2:2023, API3:2023, API4:2023, API5:2023, API6:2023, API7:2023, API8:2023, API9:2023, API10:2023, A05:2021] |
null |
|
owasp_asvs |
Literal[V2, V3, V4, V5, V6, V7, V8, V9, V11, V12, V13, V14] |
null |
|
owasp_llm |
Literal[LLM01, LLM02, LLM03, LLM04, LLM05, LLM06, LLM07, LLM08, LLM09, LLM10] |
null |
|
pci-dss |
Literal[1.2.3, 1.3, 1.3.7, 2.2.2, 2.2.5, 3.4, 3.5, 4.1, 6.1, 6.2, 6.5, 6.5.1, 6.5.2, 6.5.3, 6.5.4, 6.5.5, 6.5.6, 6.5.7, 6.5.8, 6.5.9, 6.5.10, 7.1, 7.1.2, 8.2, 8.2.1, 10.2.4] |
null |
|
psd2 |
Literal[Article-5, Article-21, Article-32, Article-94, Article-95, Article-96, Article-97, Article-98] |
null |
|
soc2 |
Literal[CC1, CC2, CC4, CC5, CC6, CC7, CC9] |
null |
|
wasc |
Literal[WASC-02, WASC-04, WASC-08, WASC-09, WASC-10, WASC-11, WASC-13, WASC-14, WASC-15, WASC-19, WASC-20, WASC-22, WASC-24, WASC-25, WASC-26, WASC-31, WASC-33, WASC-34, WASC-38, WASC-40, WASC-42, WASC-43, WASC-45, WASC-47, WASC-48] |
null |
CurlSeeder¶
| Property | Type | Default | Description |
|---|---|---|---|
curl* |
string |
The curl command to use for the request. | |
protocol* |
Const[curl] |
curl |
Inject a request specified as a curl command. Useful when youalready have a working curl one-liner from browser DevTools(Network tab → Right-click → Copy as cURL) or Postman, and youwant to drop it in as-is.yamlseed: - protocol: curl user: admin curl: > curl -X POST '[example.com](https://example.com/api/users') -H 'Content-Type: application/json' -d '{"name": "tester"}'For long-lived rules prefer the rest seeder (clearer diff,auto-filled host). |
user |
string |
null |
The user to use for the request. If not provided, the request is sent without authentication. |
CustomRuleID¶
| Property | Type | Default | Description |
|---|---|---|---|
FingerprintCountDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
gt |
integer |
null |
Condition is greater than this integer |
if* |
Const[helpers.fingerprints.count] |
helpers.fingerprints.count |
Use this to select and compare the count of unique fingerprints of the current and original response. |
in |
List[integer] |
null |
Condition is in this list of integers (exact match) |
is |
integer |
null |
Condition is this exact integer |
is_not |
integer |
null |
Condition is not this exact integer |
lt |
integer |
null |
Condition is less than this integer |
FingerprintsSameDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[helpers.fingerprints.same] |
helpers.fingerprints.same |
Use this to determine whether the current and original responses have the same fingerprint. |
is |
boolean |
null |
Condition is true |
is_not |
boolean |
null |
Condition is false |
HTTPRAWSeeder¶
| Property | Type | Default | Description |
|---|---|---|---|
protocol* |
Const[http] |
http |
Inject a request at scan start, formatted as a raw HTTP messagewith a @Host directive. Use when you need full control over thewire format, want to call a host outside the scan target, or neednon-standard headers / methods.```yamlseed: - protocol: http raw: |
Use the raw HTTP seeder to call a private host
(internal.example.com) and alert on a successful response when
the production environment is not isolated from internal services.
Multi-environment platforms expect production runtime to be
network-isolated from internal/back-office services. When a
production-runtime container can resolve and reach
internal.example.com, a single SSRF or admin-route mistake
becomes a path into the internal network.
The seeder uses the raw HTTP seeder (with the @Host directive)
so the request actually leaves the application's normal
base_url and goes to the internal hostname.
When to use: Run this from the same scanning environment you want to validate.
Replace internal.example.com with the actual hostname you want
to assert is unreachable.
OWASP: A05:2021 Security Misconfiguration · CWE: CWE-918
Severity rationale: HIGH when paired with any user-controlled URL fetch in the API; MEDIUM as a standalone configuration finding.
Features used: seed, detect, http raw seeder with @Host directive
rule:
id: example-api-environment-isolation-internal-host
type: API
alert:
name: Production environment can reach internal host
context: |
A request issued to `internal.example.com` from the production
scanner returned a successful response. The runtime
environment is not isolated from internal services.
severity: HIGH
category: REQUEST_FORGERY
seed:
- protocol: http
raw: |
@Host: https://internal.example.com
GET /api/health HTTP/1.1
Host: internal.example.com
detect:
- if: schema.url
contains: internal.example.com
- if: helpers.response.is_successful
is: true
References:
- https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
- https://cwe.mitre.org/data/definitions/918.html
For standard REST endpoints prefer the
restseeder (auto-fillshost and scheme from the scan target). | |raw* |string| | The raw HTTP request in Nuclei format. | |user|string|null| The user to use for the request. If not provided, the request is sent without authentication. |
HelpersRequestCrudDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[helpers.request.crud] |
helpers.request.crud |
Use this to select against the detected CRUD operation of the request.### Exampleyamldetect: - if: helpers.request.crud in: - CREATE - UPDATE |
in |
List[CRUD] |
null |
Condition is the request is in this list of CRUD operations (exact match) |
is |
CRUD | null |
Condition is the request is this CRUD operation |
is_not |
CRUD | null |
Condition is the request is not this CRUD operation |
HelpersResponseIsSuccessfulDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[helpers.response.is_successful] |
helpers.response.is_successful |
True when the response status code is in the 2xx range.Matcher type: BooleanMatcher · Operators: is````yamldetect: - if: helpers.response.is_successful is: true```In context — combine withhelpers.request.crudandrequest.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 is not 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
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
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://cwe.mitre.org/data/definitions/306.html
|
|
is|boolean|null| Condition is true | |is_not|boolean|null| Condition is false |
JSONMatchesAllDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[helpers.json_matches.all] |
helpers.json_matches.all |
Use this to determine whether every the current and original responses contain the same JSON fragment. |
is |
boolean |
null |
Condition is true |
is_not |
boolean |
null |
Condition is false |
jq |
string |
Use this to select the exact JSON you want to compare between the current and original response. |
JSONMatchesCountDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
gt |
integer |
null |
Condition is greater than this integer |
if* |
Const[helpers.json_matches.count] |
helpers.json_matches.count |
Use this to count the number of times a JSON match is in the current and original response. |
in |
List[integer] |
null |
Condition is in this list of integers (exact match) |
is |
integer |
null |
Condition is this exact integer |
is_not |
integer |
null |
Condition is not this exact integer |
jq |
string |
Use this to select the exact JSON you want to compare between the current and original response. | |
lt |
integer |
null |
Condition is less than this integer |
JsonValue¶
| Property | Type | Default | Description |
|---|---|---|---|
Middleware¶
ObjectMatcher¶
| Property | Type | Default | Description |
|---|---|---|---|
name |
StringMatcher | null |
Object scalar name to match |
type |
ObjectTypeMatcher | null |
Object scalar type to match |
value |
StringMatcher | null |
Object scalar value to match |
ObjectTypeMatcher¶
| Property | Type | Default | Description |
|---|---|---|---|
in |
List[OBJECT_TYPE] |
null |
Object type is in the following list |
is |
OBJECT_TYPE | null |
Object type is exactly this type |
is_not |
OBJECT_TYPE | null |
Object type is any this type except this one |
RESTSeeder¶
| Property | Type | Default | Description |
|---|---|---|---|
body |
string |
null |
The body to use for the request. |
headers |
Dict[string, string] |
null |
The headers to use for the request. The key is the header name and the value is the header value. |
method |
HTTPMethod | null |
The method to use for the request. |
params |
Dict[string, string] |
null |
parameters to use for the request. The key is the parameter name and the value is the parameter value. |
path |
string |
null |
The path to use for the request. |
protocol* |
Const[rest] |
rest |
Inject a REST request at scan start. Host and scheme areautomatically filled from the scan target so you only specify thepath, method, and any headers / body / query parameters.yamlseed: - protocol: rest path: /api/users method: GET user: admin headers: Content-Type: application/json body: '{"name": "tester"}' params: limit: '100'In context — Spring Boot actuator probing:#### Spring Boot actuator /env endpoint exposed |
Probe the Spring Boot actuator /env and /beans endpoints
(with and without the /actuator prefix) and alert if the body
leaks JAVA_HOME — proof the actuator is reachable.
Spring Boot's actuator exposes deep introspection endpoints
(/env, /beans, /heapdump, /configprops, /mappings) that
in default 1.x configurations were public. They leak environment
variables, database connection strings, JWT secrets, S3
credentials, anything passed via -D flags or env vars.
The rule probes the four most common path layouts and asserts a
successful response containing JAVA_HOME, which is virtually
certain to be present in /env output.
When to use: Any backend potentially using Spring Boot. False-positive rate
is very low because the JAVA_HOME marker rarely appears in
legitimate API responses.
OWASP: API8:2023 Security Misconfiguration · CWE: CWE-200
Severity rationale: HIGH — actuator output usually contains credentials, signing keys, and infrastructure URLs that lead to direct compromise.
Features used: seed, detect, helpers.response.is_successful, response.body.text contains
rule:
id: example-api-spring-boot-actuator-env
type: API
alert:
name: Spring Boot actuator /env exposed
context: |
A request to the Spring Boot actuator `/env` endpoint returned
a successful response containing `JAVA_HOME`, indicating the
actuator is publicly reachable and leaking environment data.
severity: HIGH
category: INFORMATION_DISCLOSURE
seed:
- protocol: rest
method: GET
path: /actuator/env
headers: {}
- protocol: rest
method: GET
path: /actuator/beans
headers: {}
- protocol: rest
method: GET
path: /env
headers: {}
- protocol: rest
method: GET
path: /beans
headers: {}
detect:
- if: helpers.response.is_successful
is: true
- if: response.body.text
contains: JAVA_HOME
References:
- https://owasp.org/API-Security/editions/2023/en/0xa8-security-misconfiguration/
- https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html
- https://cwe.mitre.org/data/definitions/200.html
In context — exposed SQL dump probing with
Rangeheader:#### Exposed SQL dumps reachable over HTTP { #example-api-information-disclosure-exposed-sql-dumps }
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 does not
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
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
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://cwe.mitre.org/data/definitions/540.html
|
|
user|string|null| The user to use for the request. If not provided, the request is sent without authentication. |
RegexMatchesAllDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[helpers.regex_matches.all] |
helpers.regex_matches.all |
Use this to determine whether every the current and original responses match the same regular expression. |
is |
boolean |
null |
Condition is true |
is_not |
boolean |
null |
Condition is false |
regex |
string |
Condition is matched on this regex with fullmatch |
RegexMatchesCountDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
gt |
integer |
null |
Condition is greater than this integer |
if* |
Const[helpers.regex_matches.count] |
helpers.regex_matches.count |
Use this to count the number of times a regex match is in the current and original response. |
in |
List[integer] |
null |
Condition is in this list of integers (exact match) |
is |
integer |
null |
Condition is this exact integer |
is_not |
integer |
null |
Condition is not this exact integer |
lt |
integer |
null |
Condition is less than this integer |
regex |
string |
Condition is matched on this regex with fullmatch |
RegexReplace¶
| Property | Type | Default | Description |
|---|---|---|---|
pattern* |
string |
The regex pattern to match. | |
replacement* |
string |
The replacement, use \1, \2, ... to refer capture groups. | |
use_extraction |
boolean |
false |
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. |
RequestArgument¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
jq |
string |
null |
JQ query to apply to the JSON body. See stedolan.github.io |
key* |
Const[request.argument] |
request.argument |
You can use this extractor to extract an argument from request body as a variable.### ExampleThis example will extract the request argument value if it matches the given scalar and store it in the variable arg.yamlextractors: extract: - key: request.argument variable: 'arg' scalars: - id - uuidThis example will extract the user ID sent in a request body JSON and store it in the variable arg.yamlextractors: extract: - key: request.argument variable: 'arg' jq: '.user.id' |
scalars |
List[string] |
null |
Scalars the argument has to match to be extracted |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
RequestBodyJSONDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[request.body.json] |
request.body.json |
Use this to select and compare the request body when detected as JSON, using jq-like syntax.### Example 1yamldetect: - if: request.body.json is: id: 42### Example 2yamldetect: - if: request.body.json jq: '.role == admin' |
in |
List[JsonValue] |
null |
Condition is in this list of JSON |
is |
JsonValue | null |
Condition is this exact JSON |
is_not |
JsonValue | null |
Condition is not this exact JSON |
jq |
string |
null |
JQ query to match and use as boolean. If use_extraction is True, only this attribute will be parsed (if set). |
use_extraction |
boolean |
false |
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. |
RequestBodyJSONMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
jq |
string |
null |
JQ query to apply to the JSON body. See stedolan.github.io |
key* |
Const[request.body.json] |
request.body.json |
Transform the JSON body of the request using a JQ expression. JQ isthe most powerful mutator in the DSL: it can add fields, removefields, walk every string, restructure objects, etc.Transformation language: JQ — see \<stedolan.github.ioyamlmutate: - key: request.body.json jq: '. + {"is_admin": true, "role": "admin"}'In context — mass assignment via privileged-field injection:#### Mass assignment via role injection in JSON body |
Inject role: admin (and friends) into every successful JSON write
issued by a regular user; alert if the modified request still
succeeds — the API failed to filter dangerous fields.
Mass assignment (a.k.a. autobinding, BOPLA) happens when an API
deserializes a client JSON payload directly into a server-side data model
without a field allow-list. An attacker can then pass extra fields
(is_admin, role, verified, subscription_tier, ...) and
elevate their own state.
The deterministic test:
transform.triggerselects every successful CREATE / UPDATE issued bytester@example.comwhose JSON body does not yet carry an admin marker.transform.mutateaddsis_admin: trueandrole: adminusing a JQ expression.detectfires when the augmented request is still successful — proving the server accepted the privileged fields.
When to use: Any REST or GraphQL endpoint that accepts a JSON object describing a user-owned resource (profile, account, organization, settings). Adjust the JQ expression to the field names your API uses.
OWASP: API3:2023 BOPLA · CWE: CWE-915
Severity rationale: HIGH — successful mass assignment typically grants full admin impersonation or unbounded subscription upgrades.
Features used: transform, detect, request.body.json mutator (jq), helpers.request.crud
rule:
id: example-api-mass-assignment-role-injection
type: API
alert:
name: Mass assignment accepted privileged fields
context: |
A request augmented with `is_admin: true` and `role: admin` was
accepted by the API. The endpoint deserializes user-supplied
fields into a server-side data model without a field allow-list.
severity: HIGH
category: ACCESS_CONTROL
transform:
trigger:
- if: helpers.response.is_successful
is: true
- if: helpers.request.crud
in:
- CREATE
- UPDATE
- if: request.user
is: tester@example.com
mutate:
- key: request.body.json
jq: '. + {"is_admin": true, "role": "admin"}'
detect:
- if: helpers.response.is_successful
is: true
References:
- https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/
- https://cwe.mitre.org/data/definitions/915.html
- https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html In context — fuzz every string in the body with a SQL-breaking suffix:#### SQL injection in JSON body via JQ-targeted payloads { #example-api-injection-sql-injection-jq-string-fields }
Walk every string field of a successful JSON request body and append a SQL-breaking payload to its value, then alert on a DBMS error in the response.
REST APIs that consume JSON usually deserialize it into typed objects. The classic concatenation-style SQLi sink is then accessible via any user-controlled string field that is passed unvalidated into a query.
The transform uses a JQ expression that walks the JSON structure
and rewrites every string leaf by appending ' OR 1=1--. The
detector then looks for the same DBMS error fingerprints used by
the text-based SQLi rule.
When to use: Any REST or GraphQL endpoint that accepts JSON. Pair with the error-disclosure SQLi rule for text-encoded request bodies.
OWASP: A03:2021 Injection · CWE: CWE-89
Severity rationale: HIGH — same impact as classic SQLi.
Features used: transform, detect, request.body.json mutator (jq), response.body.text regex
rule:
id: example-api-sql-injection-jq-string-fields
type: API
alert:
name: SQL injection via JSON string field
context: |
A SQL-breaking suffix appended to every string value in the
request body caused the API to leak a DBMS error string in the
response.
severity: HIGH
category: INJECTION
transform:
trigger:
- if: helpers.response.is_successful
is: true
- if: request.body.json
jq: any(.. | strings)
mutate:
- key: request.body.json
jq: (.. | strings) |= . + "' OR 1=1--"
detect:
- if: response.body.text
regex: .*(syntax error|sql error|ORA-[0-9]+|mysql_fetch|psql:|sqlite3.OperationalError|SQLSTATE\[).*
References:
- https://owasp.org/Top10/A03_2021-Injection/
- https://cwe.mitre.org/data/definitions/89.html
Tip: test your JQ queries at \<jqplay.org before using them. |
|
use_extraction|boolean|false| 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. |
RequestBodyTextDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[request.body.text] |
request.body.text |
Use this to select and compare the request body as text, using string compare.### Exampleyamldetect: - if: request.body.text contains: 'password=' |
in |
List[string] |
null |
Condition is in this list (case-insensitive) |
is |
string |
null |
Condition is this string (case-insensitive) |
is_not |
string |
null |
Condition is not this string (case-insensitive) |
regex |
string |
null |
Condition is matched on this regex with fullmatch (case-insensitive) |
use_extraction |
boolean |
false |
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. |
RequestBodyTextMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
key* |
Const[request.body.text] |
request.body.text |
You can use this mutator to change the body (as text) of the request before resending it.### Exampleyamltransform: trigger: - if: request.body.text contains: 'hello' mutate: - key: request.body.text values: - 'injection 1' - 'injection 2' - 'injection 3' |
regex_replace |
RegexReplace | null |
Regex replace pattern. |
use_extraction |
boolean |
false |
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. |
value |
string |
null |
The value to set. |
values |
List[string] |
null |
The values to set, generates multiple queries. |
RequestCookieExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[request.cookies] |
request.cookies |
You can use this extractor to extract variables from the request cookies.### ExampleThis example will extract a session cookie sent in request (cookie) and store it in the variable session.yamlextractors: trigger: - if: response.status_code is: 200 extract: - key: request.cookies name: 'session' variable: 'session' |
name* |
string |
Cookie name to extract from | |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
RequestHeadersDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[request.headers] |
request.headers |
Use that to select and compare the request headers in a key value dictionary.### Exampleyamldetect: - if: request.headers key: is: 'X-OPERATION' value: is: 'PAY' |
key |
StringMatcher | null |
Key to match |
value |
StringMatcher | null |
Value to match |
RequestHeadersMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
delete |
boolean |
null |
Delete the matched headers. |
key* |
Const[request.headers] |
request.headers |
You can use this mutator to change the headers of the request before resending it. If no header is matched, a new header will be added and set to the value.### Exampleyamltransform: trigger: - if: schema.url is: '/api/v1/tested/route' mutate: - key: request.headers name: X-API-version value: 'APIV2' |
name* |
string |
The header name to match, supports regex. | |
regex_replace |
RegexReplace | null |
Regex replace pattern. |
use_extraction |
boolean |
false |
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. |
value |
string |
null |
The value to set. |
values |
List[string] |
null |
The values to set, generates multiple queries. |
RequestIsAuthenticatedDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[request.is_authenticated] |
request.is_authenticated |
Use this to select whether the request is authenticated.### Exampleyamldetect: - if: request.is_authenticated is: true |
is |
boolean |
null |
Condition is true |
is_not |
boolean |
null |
Condition is false |
RequestMethodDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[request.method] |
request.method |
Use this to select against the request HTTP Method.### Exampleyamldetect: - if: request.method is: OPTIONS |
in |
List[HTTPMethod] |
null |
Condition is the request is in this list of CRUD operations (exact match) |
is |
HTTPMethod | null |
Condition is the request is this CRUD operation |
is_not |
HTTPMethod | null |
Condition is the request is not this CRUD operation |
RequestMethodMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
key* |
Const[request.method] |
request.method |
Change the HTTP method of the request before resending it.yamlmutate: - key: request.method value: DELETE# Multiple methods (one mutated request per value):mutate: - key: request.method values: [POST, PUT, DELETE, PATCH]In context — horizontal privilege escalation via user swap on a write:#### Horizontal privilege escalation via user swap on a write |
Re-issue every successful CREATE / UPDATE / DELETE issued by
tester@example.com as attacker@example.com and alert if the
write still succeeds — the endpoint is missing horizontal
authorization.
Horizontal authorization failures appear when user A can perform a state-changing operation on a resource that belongs to user B. Unlike BOLA (which is read-side), this rule targets writes: delete-someone-else's-record, update-someone-else's-profile, cancel-someone-else's-order.
The trigger picks successful writes by tester@example.com. The
mutator switches request.user to attacker@example.com. If the
replayed write is still successful, the API never re-checked
ownership of the targeted resource against the new caller.
When to use: Any API where users can mutate records keyed by a path/body id.
Pair with the platform's authentication configuration: define
tester@example.com and attacker@example.com with disjoint
resources before enabling this rule.
OWASP: API1:2023 BOLA · CWE: CWE-639
Severity rationale: HIGH — horizontal write escalation typically lets attackers delete or alter records belonging to other tenants and can be weaponized for denial-of-service or sabotage.
Features used: transform, detect, helpers.request.crud, request.user mutator
rule:
id: example-api-horizontal-privilege-escalation-write
type: API
alert:
name: Horizontal privilege escalation on write
context: |
A successful write issued by `tester@example.com` was replayed as
`attacker@example.com` and still succeeded. The endpoint is
missing a horizontal authorization check.
severity: HIGH
category: ACCESS_CONTROL
transform:
trigger:
- if: helpers.response.is_successful
is: true
- if: helpers.request.crud
in:
- CREATE
- UPDATE
- DELETE
- if: request.user
is: tester@example.com
mutate:
- key: request.user
value: attacker@example.com
detect:
- if: helpers.response.is_successful
is: true
References:
- https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/
- https://cwe.mitre.org/data/definitions/639.html
|
|
value| HTTPMethod |null| The value to set. | |values|List[HTTPMethod]|null| The values to set, generates multiple queries. |
RequestObjectDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[request.object] |
request.object |
Use this to select and compare the detected object scalars (including custom scalars) in the request, with their kind, name and value.### Exampleyamldetect: - if: request.object type: in: - email - phone - street_address |
name |
StringMatcher | null |
Object scalar name to match |
type |
ObjectTypeMatcher | null |
Object scalar type to match |
value |
StringMatcher | null |
Object scalar value to match |
RequestObjectMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
key* |
Const[request.object] |
request.object |
The detected object scalars (including custom scalars) in the request, with their kind, name and value.### Exampleyamltransform: trigger: - if: schema.url is: '/api/v1/tested/route' mutate: - key: request.object select: type: is: email name: is: 'admin_email' value: regex: .*@escape.tech mutate: regex_replace: pattern: (.*)@escape.tech replacement: \1@attacker.com |
mutate* |
BaseStringMutate | ||
select* |
ObjectMatcher |
RequestUserDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[request.user] |
request.user |
Match the user name attached to the request. The value must match auser defined in your scan authentication settings (the special userpublic represents an unauthenticated caller).Matcher type: StringMatcher · Operators: is, is_not, contains, regex, `in````yamldetect: - 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 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:
transform.triggerselects every successful request issued bytester@example.com.transform.mutatere-issues that request withrequest.userset toattacker@example.com.detectfires 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
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
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://cwe.mitre.org/data/definitions/639.html
|
|
in|List[string]|null| Condition is in this list (case-insensitive) | |is|string|null| Condition is this string (case-insensitive) | |is_not|string|null| Condition is not this string (case-insensitive) | |regex|string|null| Condition is matched on this regex with fullmatch (case-insensitive) | |use_extraction|boolean|false| 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. |
RequestUserMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
drop_user |
boolean |
null |
Remove the user authentication from the request. |
key* |
Const[request.user] |
request.user |
Replay the request as a different authenticated user (or as anonymousvia drop_user: true). The user must be defined in your scanauthentication settings.yamlmutate: - key: request.user value: attacker@example.com# Remove authentication entirely:mutate: - key: request.user drop_user: trueIn context — horizontal authorization test on a write:#### Horizontal privilege escalation via user swap on a write |
Re-issue every successful CREATE / UPDATE / DELETE issued by
tester@example.com as attacker@example.com and alert if the
write still succeeds — the endpoint is missing horizontal
authorization.
Horizontal authorization failures appear when user A can perform a state-changing operation on a resource that belongs to user B. Unlike BOLA (which is read-side), this rule targets writes: delete-someone-else's-record, update-someone-else's-profile, cancel-someone-else's-order.
The trigger picks successful writes by tester@example.com. The
mutator switches request.user to attacker@example.com. If the
replayed write is still successful, the API never re-checked
ownership of the targeted resource against the new caller.
When to use: Any API where users can mutate records keyed by a path/body id.
Pair with the platform's authentication configuration: define
tester@example.com and attacker@example.com with disjoint
resources before enabling this rule.
OWASP: API1:2023 BOLA · CWE: CWE-639
Severity rationale: HIGH — horizontal write escalation typically lets attackers delete or alter records belonging to other tenants and can be weaponized for denial-of-service or sabotage.
Features used: transform, detect, helpers.request.crud, request.user mutator
rule:
id: example-api-horizontal-privilege-escalation-write
type: API
alert:
name: Horizontal privilege escalation on write
context: |
A successful write issued by `tester@example.com` was replayed as
`attacker@example.com` and still succeeded. The endpoint is
missing a horizontal authorization check.
severity: HIGH
category: ACCESS_CONTROL
transform:
trigger:
- if: helpers.response.is_successful
is: true
- if: helpers.request.crud
in:
- CREATE
- UPDATE
- DELETE
- if: request.user
is: tester@example.com
mutate:
- key: request.user
value: attacker@example.com
detect:
- if: helpers.response.is_successful
is: true
References:
- https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/
- https://cwe.mitre.org/data/definitions/639.html In context — BOLA via user swap with fingerprint comparison:#### BOLA via user swap with fingerprint comparison { #example-api-access-control-bola-user-swap-fingerprint }
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 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:
transform.triggerselects every successful request issued bytester@example.com.transform.mutatere-issues that request withrequest.userset toattacker@example.com.detectfires 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
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
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://cwe.mitre.org/data/definitions/639.html
|
|
regex_replace| RegexReplace |null| Regex replace pattern. | |use_extraction|boolean|false| 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. | |value|string|null| The value to set. | |values|List[string]|null| The values to set, generates multiple queries. |
ResponseBodyJSONDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[response.body.json] |
response.body.json |
Use this to select and compare the response body when detected as JSON, using jq-like syntax.### Example 1yamldetect: - if: response.body.json is: id: 42### Example 2yamldetect: - if: response.body.json jq: '.role == admin' |
in |
List[JsonValue] |
null |
Condition is in this list of JSON |
is |
JsonValue | null |
Condition is this exact JSON |
is_not |
JsonValue | null |
Condition is not this exact JSON |
jq |
string |
null |
JQ query to match and use as boolean. If use_extraction is True, only this attribute will be parsed (if set). |
use_extraction |
boolean |
false |
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. |
ResponseBodyJSONExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
jq* |
string |
JQ query to apply to the JSON body. See stedolan.github.io | |
key* |
Const[response.body.json] |
response.body.json |
You can use this extractor to extract variables from the response body JSON.### ExampleThis example will extract the user ID from the response body JSON and store it in the variable user_id.yamlextractors: trigger: - if: response.status_code is: 200 extract: - key: response.body.json jq: '.user.id' variable: 'user_id' |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
ResponseBodyTextDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[response.body.text] |
response.body.text |
Use this to select and compare the response body as text, using string compare.### Exampleyamldetect: - if: request.body.text is_not: 'unauthorized' |
in |
List[string] |
null |
Condition is in this list (case-insensitive) |
is |
string |
null |
Condition is this string (case-insensitive) |
is_not |
string |
null |
Condition is not this string (case-insensitive) |
regex |
string |
null |
Condition is matched on this regex with fullmatch (case-insensitive) |
use_extraction |
boolean |
false |
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. |
ResponseBodyTextExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[response.body.text] |
response.body.text |
You can use this extractor to extract variables from the response body text.### ExampleThis example will extract the response body text and store it in the variable body_data.yamlextractors: trigger: - if: response.status_code is: 200 extract: - key: response.body.text variable: 'body_data' |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
ResponseCookieExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[response.cookies] |
response.cookies |
You can use this extractor to extract variables from the response cookies.### ExampleThis example will extract a session cookie returned in response (set-cookie) and store it in the variable session.yamlextractors: trigger: - if: response.status_code is: 200 extract: - key: response.cookies name: 'session' variable: 'session' |
name* |
string |
Cookie name to extract from | |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
ResponseDurationDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
gt |
integer |
null |
Condition is greater than this integer |
if* |
Const[response.duration_ms] |
response.duration_ms |
Use this to compare the duration of the request in milliseconds.### Exampleyamldetect: - if: response.duration_ms gt: 200 |
in |
List[integer] |
null |
Condition is in this list of integers (exact match) |
is |
integer |
null |
Condition is this exact integer |
is_not |
integer |
null |
Condition is not this exact integer |
lt |
integer |
null |
Condition is less than this integer |
ResponseDurationExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[response.duration] |
response.duration |
You can use this extractor to extract the response duration as a variable.### ExampleThis example will extract the response duration and store it in the variable duration.yamlextractors: extract: - key: response.duration variable: 'duration' |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
ResponseHeaderExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[response.headers] |
response.headers |
You can use this extractor to extract variables from the response headers.### ExampleThis example will extract a token from the response header X-Token and store it in the variable x_token.yamlextractors: trigger: - if: response.status_code is: 200 extract: - key: response.headers name: 'X-Token' variable: 'x_token' |
name* |
string |
Header name to extract from | |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
ResponseHeadersDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[response.headers] |
response.headers |
Use that to select and compare the response headers in a key value dictionary.### Exampleyamldetect: - if: response.headers key: is: 'X-RESULT' value: is: 'PAID' |
key |
StringMatcher | null |
Key to match |
value |
StringMatcher | null |
Value to match |
ResponseObjectDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[response.object] |
response.object |
Use this to select and compare the detected object scalars (including custom scalars) in the response, with their kind, name and value.### Exampleyamldetect: - if: response.object type: in: - email - phone - street_address |
name |
StringMatcher | null |
Object scalar name to match |
type |
ObjectTypeMatcher | null |
Object scalar type to match |
value |
StringMatcher | null |
Object scalar value to match |
ResponseStatusCodeDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
gt |
integer |
null |
Condition is greater than this integer |
if* |
Const[response.status_code] |
response.status_code |
Match against the HTTP response status code.Matcher type: IntegerMatcher · Operators: is, is_not, gt, lt, in````yamldetect: - if: response.status_code in: [200, 206]```For simple success/failure checks preferhelpers.response.is_successful` (it covers the full 2xx range andis 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 does not
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
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
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://cwe.mitre.org/data/definitions/540.html
|
|
in|List[integer]|null| Condition is in this list of integers (exact match) | |is|integer|null| Condition is this exact integer | |is_not|integer|null| Condition is not this exact integer | |lt|integer|null| Condition is less than this integer |
ResponseStatusCodeExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[response.status_code] |
response.status_code |
You can use this extractor to extract the response status code as a variable.### ExampleThis example will extract the response status code and store it in the variable status_code.yamlextractors: extract: - key: response.status_code variable: 'status_code' |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
ScanTypeDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[scan.type] |
scan.type |
Match against the type of scan being performed.Matcher Type: ScanTypeMatcher · Operators: is, is_not, in · Valid values: REST, `GRAPHQL````yamldetect: - if: scan.type is: REST# ORdetect: - if: scan.type in: [REST, GRAPHQL]``` |
in |
List[CustomRuleScanType] |
null |
The scan type is in this list |
is |
CustomRuleScanType | null |
The scan type is exactly this |
is_not |
CustomRuleScanType | null |
The scan type is not this type |
SchemaNeedAuthenticationDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[schema.need_authentication] |
schema.need_authentication |
Use this to select whether or not the schema requires authentication.### Exampleyamldetect: - if: schema.need_authentication is: false |
is |
boolean |
null |
Condition is true |
is_not |
boolean |
null |
Condition is false |
SchemaPathRefDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[schema.path_ref] |
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````yamldetect: - 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
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
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://cwe.mitre.org/data/definitions/862.html
|
|
in|List[string]|null| Condition is in this list (case-insensitive) | |is|string|null| Condition is this string (case-insensitive) | |is_not|string|null| Condition is not this string (case-insensitive) | |regex|string|null| Condition is matched on this regex with fullmatch (case-insensitive) | |use_extraction|boolean|false| 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. |
SchemaPathRefMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
key* |
Const[schema.path_ref] |
schema.path_ref |
You can use this mutator to change the operation name in GraphQL or the path in REST (keeping the domain) before resending it.### Exampleyamltransform: trigger: - if: schema.path_ref is: '/api/v1/tested/route' mutate: - key: schema.path_ref mutate: value: '/api/v2/tested/route' |
regex_replace |
RegexReplace | null |
Regex replace pattern. |
use_extraction |
boolean |
false |
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. |
value |
string |
null |
The value to set. |
values |
List[string] |
null |
The values to set, generates multiple queries. |
SchemaUrlDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[schema.url] |
schema.url |
Use this to string compare the URL of the request.### Example```yamldetect: - if: schema.url regex: .*(internal |
in |
List[string] |
null |
Condition is in this list (case-insensitive) |
is |
string |
null |
Condition is this string (case-insensitive) |
is_not |
string |
null |
Condition is not this string (case-insensitive) |
regex |
string |
null |
Condition is matched on this regex with fullmatch (case-insensitive) |
use_extraction |
boolean |
false |
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. |
SchemaUrlExtractor¶
| Property | Type | Default | Description |
|---|---|---|---|
accept_null |
boolean |
false |
Whether the extractor should accept null values or not. |
can_overwrite |
boolean |
true |
Whether the extractor can overwrite the variable if it already exists. |
key* |
Const[schema.url] |
schema.url |
You can use this extractor to extract variables from the schema URL.### ExampleThis example will extract the schema URL and store it in the variable request_url.yamlextractors: trigger: - if: response.status_code is: 200 extract: - key: schema.url variable: 'request_url' |
variable* |
VariableName | The variable name (Case Insensitive) to store the extracted data. |
SchemaUrlMutator¶
| Property | Type | Default | Description |
|---|---|---|---|
key* |
Const[schema.url] |
schema.url |
You can use this mutator to change the URL of the request before resending it.### Exampleyamltransform: trigger: - if: schema.url is: '[api.example.com](https://api.example.com/api/v1/tested/route') mutate: - key: schema.url mutate: value: '[api2.example.com](https://api2.example.com/api/v2/') |
regex_replace |
RegexReplace | null |
Regex replace pattern. |
use_extraction |
boolean |
false |
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. |
value |
string |
null |
The value to set. |
values |
List[string] |
null |
The values to set, generates multiple queries. |
StringMatcher¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
in |
List[string] |
null |
Condition is in this list (case-insensitive) |
is |
string |
null |
Condition is this string (case-insensitive) |
is_not |
string |
null |
Condition is not this string (case-insensitive) |
regex |
string |
null |
Condition is matched on this regex with fullmatch (case-insensitive) |
use_extraction |
boolean |
false |
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. |
VariableDefinedDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[variable.defined] |
variable.defined |
Use this to detect if a given variable has been extracted or not yet.### Basic Exampleyamldetect: - 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. |
variable_name* |
string |
Use this to specify the variable name that has to be defined before proceeding further |
VariableName¶
| Property | Type | Default | Description |
|---|---|---|---|
Enums¶
CRUD¶
| Value |
|---|
CREATE |
READ |
UPDATE |
DELETE |
CustomRuleCategory¶
| Value |
|---|
ACCESS_CONTROL |
CONFIGURATION |
INFORMATION_DISCLOSURE |
INJECTION |
PROTOCOL |
REQUEST_FORGERY |
RESOURCE_LIMITATION |
SENSITIVE_DATA |
SCHEMA |
CUSTOM |
CustomRuleScanType¶
| Value |
|---|
GRAPHQL |
REST |
CustomRuleSeverity¶
| Value |
|---|
HIGH |
MEDIUM |
LOW |
INFO |
HTTPMethod¶
| Value |
|---|
CONNECT |
DELETE |
GET |
HEAD |
OPTIONS |
PATCH |
POST |
PUT |
TRACE |
OBJECT_TYPE¶
| Value |
|---|
See Data Types Reference |
WebApp reference¶
FrontendCustomRule¶
Objects¶
CheckAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[check] |
check |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
locator* |
string |
The Playwright Locator to select the checkbox to check | |
select_first_if_multiple |
boolean |
false |
Whether to select the first element if multiple elements are found. If false, an error will be raised. |
timeout |
integer |
30 |
Timeout in seconds for executing the check action |
ClickAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[click] |
click |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
locator* |
string |
The Playwright Locator to select the element to click on | |
select_first_if_multiple |
boolean |
false |
Whether to select the first element if multiple elements are found. If false, an error will be raised. |
timeout |
integer |
30 |
Timeout in seconds for executing the click action |
ClickMailMagicLinkAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[click_mail_magic_link] |
click_mail_magic_link |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
email_address* |
string |
The email address where the magic link will be sent.\nMust be a valid email address matching this pattern: {any_text}.{organization_id}@scan.escape.tech | |
new_page |
boolean |
false |
Whether to create a new page for the navigation or remain on the current page |
timeout |
integer |
60 |
The timeout (seconds) to wait for the page to load |
CookieDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[cookie] |
cookie |
Use this to assert that a cookie is present in the browser.### Exampleyamldetect: - if: cookie key: 'my-key' value: 'pattern' |
key |
StringMatcher | null |
Key to match |
value |
StringMatcher | null |
Value to match |
DialogMessageDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[dialog.message] |
dialog.message |
Use this to assert that a JavaScript dialog (alert, confirm,prompt) was triggered by the page and inspect its message. Usefulfor catching reflected XSS payloads that fire alert() oncerendered.### Exampleyamldetect: - if: dialog.message contains: 'XSS' |
in |
List[string] |
null |
Condition is in this list (case-insensitive) |
is |
string |
null |
Condition is this string (case-insensitive) |
is_not |
string |
null |
Condition is not this string (case-insensitive) |
regex |
string |
null |
Condition is matched on this regex with fullmatch (case-insensitive) |
use_extraction |
boolean |
false |
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. |
FillAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[fill] |
fill |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
auto_submit |
boolean |
false |
Whether the form should be automatically submitted after the fill action |
locator* |
string |
The Playwright Locator to select the field to fill | |
one_by_one |
boolean |
false |
Whether the field should be typed one character by one character, like a TOTP code |
select_first_if_multiple |
boolean |
false |
Whether to select the first element if multiple elements are found. If false, an error will be raised. |
timeout |
integer |
30 |
Timeout in seconds for executing the input filling action |
value* |
string |
The value to fill in the field |
FillMailTOTPAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action |
Literal[fill_mail_totp, fill_email_totp] |
fill_email_totp |
Use fill_email_totp. fill_mail_totp is deprecated and can be removed in the future. |
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
auto_submit |
boolean |
false |
Whether the form should be automatically submitted after the fill action |
email_address* |
string |
The email address where the TOTP code will be sent.\nMust be a valid email address matching this pattern: {any_text}.{organization_id}@scan.escape.tech | |
locator* |
string |
The Playwright Locator to select the field to fill | |
one_by_one |
boolean |
false |
Whether the field should be typed one character by one character, like a TOTP code |
select_first_if_multiple |
boolean |
false |
Whether to select the first element if multiple elements are found. If false, an error will be raised. |
timeout |
integer |
30 |
Timeout in seconds for executing the input filling action |
FillTOTPAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[fill_totp] |
fill_totp |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
auto_submit |
boolean |
false |
Whether the form should be automatically submitted after the TOTP code is filled |
locator* |
string |
The Playwright Locator to select the field to fill the TOTP code in | |
secret* |
string |
The secret to generate the TOTP code from |
FocusPageAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[focus_page] |
focus_page |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
url_pattern* |
string |
The pattern to find in the URL to focus on a page. Should be a regex allowing to match the page using Python re.findall(). |
FrontendGotoAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[goto] |
goto |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
new_page |
boolean |
false |
Whether to create a new page for the navigation or remain on the current page |
timeout |
integer |
60 |
The timeout (seconds) to wait for the page to load |
url* |
string |
The URL to navigate to | |
verify_scope |
boolean |
true |
When true, verify that the URL is within the crawling scope. When false, allow navigation to out-of-scope URLs. |
FrontendLogicalAndDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
and* |
List[CookieDetector,DialogMessageDetector,FrontendLogicalAndDetector,FrontendLogicalNotDetector,FrontendLogicalOrDetector,HeaderDetector,JSAssertionDetector,LastRequestResponseTextDetector,LocalStorageDetector,PageSelectorDetector,PageStatusCodeDetector,PageTextDetector,SessionStorageDetector] |
Logical and on a list of detectors | |
if* |
Const[and] |
and |
FrontendLogicalNotDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[not] |
not |
|
not |
CookieDetector, DialogMessageDetector, FrontendLogicalAndDetector, FrontendLogicalNotDetector, FrontendLogicalOrDetector, HeaderDetector, JSAssertionDetector, LastRequestResponseTextDetector, LocalStorageDetector, PageSelectorDetector, PageStatusCodeDetector, PageTextDetector, SessionStorageDetector | null |
Logical not of a detector |
FrontendLogicalOrDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[or] |
or |
|
or* |
List[CookieDetector,DialogMessageDetector,FrontendLogicalAndDetector,FrontendLogicalNotDetector,FrontendLogicalOrDetector,HeaderDetector,JSAssertionDetector,LastRequestResponseTextDetector,LocalStorageDetector,PageSelectorDetector,PageStatusCodeDetector,PageTextDetector,SessionStorageDetector] |
Logical or on a list of detectors |
FrontendRequestAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[send_request] |
send_request |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
body |
string |
The body to use for the request. | |
headers |
Dict[string, string] |
The headers to use for the request. | |
max_redirects |
integer |
The maximum number of redirections to follow. | |
method |
HTTPMethod | GET |
The HTTP method to use for the request. |
timeout |
integer |
60 |
The timeout (seconds) to wait for the page to load |
url* |
string |
The URL to navigate to |
HeaderDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[header] |
header |
Use this to assert that a header is present in the request.### Exampleyamldetect: - if: header key: 'my-key' value: 'pattern' |
key |
StringMatcher | null |
Key to match |
value |
StringMatcher | null |
Value to match |
JSAssertionDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
command |
string |
null |
JavaScript command to execute |
if* |
Const[js_assertion] |
js_assertion |
Use this to execute a JavaScript command and assert it returns true.### Exampleyamldetect: - if: js_assertion command: 'return window.isAuthenticated === false;' |
LastRequestResponseTextDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this substring (case-insensitive) |
if* |
Const[last_request.response.text] |
last_request.response.text |
Use this to assert that the last request response text contains a specific substring.### Exampleyamldetect: - if: last_request.response.text contains: 'Unauthorized' |
in |
List[string] |
null |
Condition is in this list (case-insensitive) |
is |
string |
null |
Condition is this string (case-insensitive) |
is_not |
string |
null |
Condition is not this string (case-insensitive) |
regex |
string |
null |
Condition is matched on this regex with fullmatch (case-insensitive) |
use_extraction |
boolean |
false |
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. |
LocalStorageDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[local_storage] |
local_storage |
Use this to assert that a key is present in the local storage.### Exampleyamldetect: - if: local_storage key: 'my-key' value: 'pattern' |
key |
StringMatcher | null |
Key to match |
value |
StringMatcher | null |
Value to match |
PageSelectorDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this string |
if* |
Const[page_selector] |
page_selector |
Use this to assert that a selector exists in the DOM.### Exampleyamldetect: - if: page_selector contains: '#my-element' |
PageStatusCodeDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
gt |
integer |
null |
Condition is greater than this integer |
if* |
Const[page_status_code] |
page_status_code |
Use this to assert that the page status code is a specific value.### Exampleyamldetect: - if: page_status_code status_code: 200 |
in |
List[integer] |
null |
Condition is in this list of integers (exact match) |
is |
integer |
null |
Condition is this exact integer |
is_not |
integer |
null |
Condition is not this exact integer |
lt |
integer |
null |
Condition is less than this integer |
PageTextDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
contains |
string |
null |
Contains this string |
if* |
Const[page_text] |
page_text |
Use this to assert that a text is present in the page.### Exampleyamldetect: - if: page_text contains: 'Hello, world!' |
SelectAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[select] |
select |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
locator* |
string |
The Playwright Locator to select the dropdown to select from | |
select_first_if_multiple |
boolean |
false |
Whether to select the first element if multiple elements are found. If false, an error will be raised. |
timeout |
integer |
30 |
Timeout in seconds for executing the click action |
value* |
string |
The value to select |
SessionStorageDetector¶
| Property | Type | Default | Description |
|---|---|---|---|
if* |
Const[session_storage] |
session_storage |
Use this to assert that a key is present in the session storage.### Exampleyamldetect: - if: session_storage key: 'my-key' value: 'pattern' |
key |
StringMatcher | null |
Key to match |
value |
StringMatcher | null |
Value to match |
SleepAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[sleep] |
sleep |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
seconds* |
number |
The time to sleep in seconds, between 0 and 40 seconds |
SolveCaptchaAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[solve_captcha] |
solve_captcha |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
auto_submit |
boolean |
false |
Whether the form should be automatically submitted after the captcha is filled |
locator* |
string |
The Playwright Locator to select the captcha field to fill |
WaitElementAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[wait_element] |
wait_element |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
locator* |
string |
The selector to wait for | |
timeout |
number |
10 |
The timeout (seconds) to wait for the element to be visible |
WaitTextAction¶
| Property | Type | Default | Description |
|---|---|---|---|
action* |
Const[wait_text] |
wait_text |
|
allow_failure |
boolean |
false |
Allow this action to fail without breaking authentication, defaults to False. |
timeout |
number |
10 |
The timeout (seconds) to wait for the text to be visible |
value* |
string |
The text to wait for until visible, case-insensitive |