Skip to content
This page was generated and translated with the assistance of AI. If you spot any inaccuracies, feel free to help improve it. Edit on GitHub

YAML Rule Syntax

This page documents the complete YAML rule schema used by PRX-WAF. Every rule file follows this structure.

File Structure

Each YAML rule file has a top-level metadata section followed by a list of rules:

yaml
version: "1.0"                     # Schema version (required)
description: "Short description"   # Human-readable label (required)
source: "OWASP CRS v4.25.0"       # Origin of the rules (optional)
license: "Apache-2.0"             # SPDX license identifier (optional)

rules:
  - <rule>
  - <rule>

Rule Schema

Each rule in the rules list has the following fields:

yaml
- id: "CRS-942100"              # Unique string ID (REQUIRED)
  name: "SQL injection attack"  # Short description (REQUIRED)
  category: "sqli"              # Category tag (REQUIRED)
  severity: "critical"          # Severity level (REQUIRED)
  paranoia: 1                   # Paranoia level 1-4 (optional, default: 1)
  field: "all"                  # Request field to inspect (REQUIRED)
  operator: "regex"             # Match operator (REQUIRED)
  value: "(?i)select.+from"     # Pattern or threshold (REQUIRED)
  action: "block"               # Action on match (REQUIRED)
  tags:                         # String tags (optional)
    - "owasp-crs"
    - "sqli"
  crs_id: 942100                # Original CRS numeric ID (optional)
  reference: "https://..."      # CVE or documentation link (optional)

Required Fields

FieldTypeDescription
idstringUnique identifier across all rule files. Format: <PREFIX>-<CATEGORY>-<NNN>
namestringShort human-readable description (max ~120 chars)
categorystringCategory tag for filtering and reporting
severitystringOne of: critical, high, medium, low, info, notice, warning, error, unknown
fieldstringWhich part of the request to inspect (see Field Reference)
operatorstringHow to match the value (see Operator Reference)
valuestringPattern, threshold, or wordlist filename
actionstringWhat to do when the rule matches (see Action Reference)

Optional Fields

FieldTypeDefaultDescription
paranoiainteger1Paranoia level 1-4
tagsstring[][]Tags for filtering and dashboard display
crs_idinteger--Original OWASP CRS numeric ID
referencestring--URL to CVE, OWASP article, or rationale

Field Reference

The field value determines which part of the HTTP request is inspected:

FieldInspects
pathRequest URI path (without query string)
queryQuery string (all parameters, decoded)
bodyRequest body (decoded)
headersAll request headers (name: value pairs)
user_agentUser-Agent header only
cookiesRequest cookies
methodHTTP method (GET, POST, PUT, etc.)
content_typeContent-Type header
content_lengthContent-Length value (for numeric comparison)
path_lengthLength of the URI path (for numeric comparison)
query_arg_countNumber of query parameters (for numeric comparison)
allAll of the above fields combined

Operator Reference

The operator value determines how the value is matched against the inspected field:

OperatorDescriptionValue Format
regexPCRE-compatible regular expressionRegex pattern
containsField contains the literal stringLiteral string
equalsField exactly equals value (case-sensitive)Literal string
not_inField value is NOT in the listComma-separated list
gtField value (numeric) is greater thanNumber string
ltField value (numeric) is less thanNumber string
geField value (numeric) is greater than or equalNumber string
leField value (numeric) is less than or equalNumber string
detect_sqliSQL injection detection via libinjection"true" or ""
detect_xssXSS detection via libinjection"true" or ""
pm_from_filePhrase-match against wordlist fileFilename in owasp-crs/data/
pmPhrase-match against inline listComma-separated phrases

Action Reference

The action value determines what happens when a rule matches:

ActionDescription
blockReject the request with a 403 Forbidden response
logAllow the request but log the match (monitoring mode)
allowExplicitly allow the request (overrides other rules)
denyAlias for block
redirectRedirect the request (engine-specific configuration)
dropSilently drop the connection

TIP

Start new rules with action: log to monitor for false positives before switching to action: block.

ID Namespace Convention

Rule IDs should follow the established prefix convention:

DirectoryID PrefixExample
owasp-crs/CRS-<number>CRS-942100
modsecurity/MODSEC-<CATEGORY>-<NNN>MODSEC-IP-001
cve-patches/CVE-<YEAR>-<SHORT>-<NNN>CVE-2021-LOG4J-001
custom/CUSTOM-<CATEGORY>-<NNN>CUSTOM-API-001

Complete Example

yaml
version: "1.0"
description: "Application-specific access control rules"
source: "custom"
license: "Apache-2.0"

rules:
  - id: "CUSTOM-API-001"
    name: "Block access to internal admin API"
    category: "access-control"
    severity: "high"
    paranoia: 1
    field: "path"
    operator: "regex"
    value: "(?i)^/internal/"
    action: "block"
    tags: ["custom", "access-control"]

  - id: "CUSTOM-BOT-001"
    name: "Log suspicious automated tool user-agents"
    category: "scanner"
    severity: "medium"
    paranoia: 2
    field: "user_agent"
    operator: "regex"
    value: "(?i)(masscan|zgrab|python-requests/|go-http-client)"
    action: "log"
    tags: ["custom", "bot", "scanner"]

  - id: "CUSTOM-RATE-001"
    name: "Block requests with excessive query parameters"
    category: "dos"
    severity: "medium"
    paranoia: 1
    field: "query_arg_count"
    operator: "gt"
    value: "50"
    action: "block"
    tags: ["custom", "dos"]

Rule Validation

Validate your rule files before deploying:

bash
# Validate all rules
python rules/tools/validate.py rules/

# Validate a specific file
python rules/tools/validate.py rules/custom/myapp.yaml

The validator checks for:

  • Required fields are present
  • No duplicate rule IDs across all files
  • Severity and action values are valid
  • Paranoia levels are in range 1-4
  • Regexes compile correctly
  • Numeric operators are not used with string values

Next Steps

Released under the Apache-2.0 License.