Cloudflare Docs
Ruleset-Engine
Visit Ruleset Engine on GitHub
Set theme to dark (⇧+D)

Functions reference

The Cloudflare Rules language provides functions for manipulating and validating values in an expression:

Transformation functions

The Rules language supports several functions that transform values extracted from HTTP requests. A common use case for transformation functions is the conversion of a string of characters to uppercase or lowercase, since by default, string evaluation is case sensitive.

For example, the lower() function converts all uppercase characters in a string to lowercase.

In the expression below, thelower() function transforms http.host values to lowercase so that they match the target value "www.cloudflare.com":

lower(http.host) == "www.cloudflare.com"

Transformation functions that do not take arrays as an argument type require the [*] special index notation. Refer to Arrays for more information.

The Rules language supports these transformation functions:

  • any(Array<Boolean>) Boolean

    • Returns true when the comparison operator in the argument returns true for any of the values in the argument array. Returns false otherwise.

    • Example:

      any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")
  • all(Array<Boolean>) Boolean

    • Returns true when the comparison operator in the argument returns true for all values in the argument array. Returns false otherwise.

    • Example:

      all(http.request.headers['content-type'][*] == "application/json")

  • concat(String | Integer | bytes | Array elements) String

    • Takes a comma-separated list of values. Concatenates the argument values into a single String.

    • Example:

      concat("String1"," ","String",2) == "String1 String2"

  • ends_with(sourceString, substringString) Boolean

    • Returns true when the source ends with a given substring. Returns false otherwise. The source cannot be a literal value (for example, "foo").

    • Example:
      If http.request.uri.path is "/welcome.html", then ends_with(http.request.uri.path, ".html") will return true.

  • len(String | bytes) Integer

    • Returns the byte length of a String or Bytes field.

    • Example:

      len(http.host)

  • lookup_json_string(fieldString, keyString) String

    • Returns the string value associated with the supplied key in field.
      The field must be a string representation of a valid JSON object.
      The key can be an attribute name, a zero-based position number in a JSON array, or a combination of these two options (as extra function parameters), while following the hierarchy of the JSON object to obtain a specific value.

    • Examples:

      A) Given the following JSON object contained in the http.request.body.raw field:
      { "company": "cloudflare", "product": "rulesets" }
      The following expression will return true:
      lookup_json_string(http.request.body.raw, "company") == "cloudflare"

      B) Given the following nested object:
      { "network": { "name": "cloudflare" } }
      The following expression will return true:
      lookup_json_string(http.request.body.raw, "network", "name") == "cloudflare"

      C) Given the following JSON array at the root level:
      ["other_company", "cloudflare"]
      The following expression will return true:
      lookup_json_string(http.request.body.raw, 1) == "cloudflare"

      D) Given the following array in a JSON object attribute:
      { "networks": ["other_company", "cloudflare"] }
      The following expression will return true:
      lookup_json_string(http.request.body.raw, "networks", 1) == "cloudflare"

      E) Given the following root-level array of JSON objects:
      [{ "network": "other_company" }, { "network": "cloudflare" }]
      The following expression will return true:
      lookup_json_string(http.request.body.raw, 1, "network") == "cloudflare"

  • lower(String) String

    • Converts a string field to lowercase. Only uppercase ASCII bytes are converted. All other bytes are unaffected.

    • Example:

      lower(http.host) == "www.cloudflare.com"

  • regex_replace(sourceString, regular_expressionString, replacementString) String

    • Replaces a part of a source string matched by a regular expression with a replacement string, returning the result. The replacement string can contain references to regular expression capture groups.

    • Examples:

      Literal match replace:
      regex_replace("/foo/bar", "/bar$", "/baz") == "/foo/baz"

      If there is no match, the input string does not change:
      regex_replace("/x", "^/y$", "/mumble") == "/x"

      Match is case sensitive by default:
      regex_replace("/foo", "^/FOO$", "/x") == "/foo"

      When there are multiple matches, only one replacement occurs (the first one):
      regex_replace("/a/a", "/a", "/b") == "/b/a"

      Escape a $ in the replacement string by prefixing it with another $:
      regex_replace("/b", "^/b$", "/b$$") == "/b$"

      Replace with capture groups:
      regex_replace("/foo/a/path", "^/foo/([^/]*)/(.*)$", "/bar/${2}/${1}") == "/bar/path/a/"

  • remove_bytes(bytes) bytes

    • Returns a new byte array with all the occurrences of the given bytes removed.

    • Example:

      remove_bytes(http.host, "\x2e\x77") == "cloudflarecom"

  • starts_with(sourceString, substringString) Boolean

    • Returns true when the source starts with a given substring. Returns false otherwise. The source cannot be a literal value (for example, "foo").

    • Example:
      If http.request.uri.path is "/blog/first-post", then starts_with(http.request.uri.path, "/blog") will return true.

  • to_string(Integer | Boolean | IP address) String

    • Returns the string representation of an Integer, Boolean, or IP address value.

    • Examples:

      to_string(cf.bot_management.score) == '5'
      to_string(ssl) == 'true'
      
  • upper(String) String

    • Converts a string field to uppercase. Only lowercase ASCII bytes are converted. All other bytes are unaffected.

    • Example:

      upper(http.host) == “WWW.CLOUDFLARE.COM”

  • url_decode(String) String

    • Decodes a URL formatted string, as in the following:

      • %20 and + decode to space characters

      • %E4%BD decodes to ä½

    • Example:

      any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")
      

Magic Firewall Functions

  • bit_slice(String, Number, Number) Number

    • Select a slice of contiguous bits from a string field. This is primarily intended for use with ip and tcp.
    • The slice can be no longer than 31 bits, but multiple calls can be joined together via a logical expression.
    • Use of structure fields is preferred over this mechanism.

HMAC validation

Overview

You can validate hash-based message authentication code (HMAC) tokens in a rule expression by using the is_timed_hmac_valid_v0() function, which has this signature:

is_timed_hmac_valid_v0(
  <String literal as Key>,
  <String field as MessageMAC>,
  <Integer literal as ttl>,
  <Integer as currentTimeStamp>,
  <Optional Integer literal as lengthOfSeparator, default: 0>,
  <Optional String literal as flags>
) -> <Bool as result>

The is_timed_hmac_valid_v0() function has these parameter definitions:

  • Key String literal

    • Specifies the secret cryptographic key for validating the HMAC.
  • MessageMAC String

    • Contains a concatenation of these HMAC elements: message, separator, timestamp, mac. For a definition and an example, refer to MessageMAC .
  • ttl Integer literal

    • Defines the time-to-live for the HMAC token, expressed in seconds. Determines how long the token is valid, relative to the time it was issued.
  • currentTimeStamp Integer

    • Represents the Unix timestamp when Cloudflare received the request, expressed in seconds. Pass the http.request.timestamp.sec field as an approximate value to this argument.
  • lengthOfSeparator Integer literal optional

    • Specifies the length of the separator between the timestamp and the message in the MessageMAC. Expressed in bytes, with a default value of 0.
  • flags String literal optional

    • When you set this optional argument to 's', the function expects the value of the base64-encoded mac in the MessageMAC argument to use the URL-safe character set with no padding.

    • When you do not set the value of flags to 's', you must URL encode the base64 value for mac in the MessageMAC argument.

Usage

The is_timed_hmac_valid_v0() function uses the supplied Key to generate a message authentication code (MAC) from the message and the timestamp regions of the MessageMAC. When the generated MAC matches the mac region of the MessageMAC and the token has not expired, the HMAC is valid and the function returns true.

For example, the following expression matches requests to download.example.com that do not include valid HMAC tokens:

http.host == "download.example.com"
and not is_timed_hmac_valid_v0("mysecretkey", http.request.uri, 100000, http.request.timestamp.sec, 8)

For examples of rules that use HMAC validation, refer to Firewall Rules: Common use cases .

MessageMAC

A valid MessageMAC satisfies the regular expression

(.+)(.*)(\d{10})-(.{43,})

and is composed of these parentheses-delimited expressions:

Expression Description Example
(.+) The message to validate. /download/cat.jpg
(.*) The separator between message and timestamp, commonly a parameter name. &verify=
(\d{10}) The 10-digit Unix timestamp when the MAC was issued, expressed in seconds. 1484063137
(.{43,})

A base64-encoded version of the MAC. When you do not set the value of the urlSafe argument in the HMAC validation function to 's', you must URL encode the base64 value for mac.

When the base64 MAC encoding is URL-safe, the value for mac contains 43 bytes. Otherwise, the value will be 44 bytes or more, because of URL encoding.

IaLGSmELTvlhfd0ItdN6PhhHTFhzx
73EX8uy%2FcSDiIU%3D

For details on generating a MessageMAC, refer to Implement token creation.

HMAC validation examples

Simple case

Consider the case where the MessageMAC is contained entirely within a single field, as in this example URI path:

/download/cat.jpg?verify=1484063787-IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

Note how the URI maps to the elements of the MessageMAC:

  • message: /download/cat.jpg
  • separator: ?verify=
  • timestamp: 1484063787
  • mac: IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D

When the MessageMAC is contained entirely within a single field such as http.request.uri, using the validation function is straightforward. Pass the name of the field to the MessageMAC argument:

is_timed_hmac_valid_v0(
  "mysecretkey",
  http.request.uri,
  100000,
  http.request.timestamp.sec,
  8
)

Concatenated MessageMAC argument

To compose a MessageMAC from more than one field, use the concat() function.

This example constructs the MessageMAC by concatenating the request URI and two header fields:

is_timed_hmac_valid_v0(
  "mysecretkey",
  concat(
    http.request.uri,
    http.request.headers["timestamp"][0],
    "-",
    http.request.headers["mac"][0]),
  100000,
  http.request.timestamp.sec,
  0
)

For more on concat() usage, refer to Transformation functions .