Cloudflare Docs
WAF
Edit this page
Give us feedback
Set theme to dark (⇧+D)

Configure exposed credentials checks via API

Configure exposed credentials checks using the Rulesets API. You can do the following:

​​ Create a custom rule checking for exposed credentials

You can create rules that check for exposed credentials using the Rulesets API. Include these rules in a custom ruleset, which you must create at the account level, and then deploy the custom ruleset to a phase.

A rule checking for exposed credentials has a match when both the rule expression and the result from the exposed credentials check are true.

To check for exposed credentials in a custom rule, include the exposed_credential_check object in the rule definition. This object must have the following properties:

  • username_expression — Expression that selects the user ID used in the credentials check. This property can have up to 1024 characters.
  • password_expression — Expression that selects the password used in the credentials check. This property can have up to 1024 characters.

You can use the exposed_credential_check object in rules with one of the following actions: rewrite, log, block, challenge, or js_challenge. Cloudflare recommends that you only use exposed credentials checks with the following actions: rewrite and log.

To create and deploy a custom ruleset, follow the workflow described in Work with custom rulesets.

​​ Example A

This POST request example creates a new custom ruleset with a rule that checks for exposed credentials. The rule has a match if both the rule expression and the exposed_credential_check result are true. When there is a match, the rule will log the request with exposed credentials in the Cloudflare logs.

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/rulesets" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{
"name": "Custom Ruleset A",
"kind": "custom",
"description": "This ruleset includes a rule checking for exposed credentials.",
"rules": [
{
"action": "log",
"description": "Exposed credentials check on login.php page",
"expression": "http.request.method == \"POST\" && http.request.uri == \"/login.php\"",
"exposed_credential_check": {
"username_expression": "url_decode(http.request.body.form[\"username\"][0])",
"password_expression": "url_decode(http.request.body.form[\"password\"][0])"
}
}
],
"phase": "http_request_firewall_custom"
}'

The response returns the created ruleset. Note the presence of the exposed_credential_check object on the rule definition.

{
"result": {
"id": "<CUSTOM_RULESET_ID>",
"name": "Custom Ruleset A",
"description": "This ruleset includes a rule checking for exposed credentials.",
"kind": "custom",
"version": "1",
"rules": [
{
"id": "<CUSTOM_RULE_ID>",
"version": "1",
"action": "log",
"description": "Exposed credentials check on login.php page",
"expression": "http.request.method == \"POST\" && http.request.uri == \"/login.php\"",
"exposed_credential_check": {
"username_expression": "url_decode(http.request.body.form[\"username\"][0])",
"password_expression": "url_decode(http.request.body.form[\"password\"][0])"
},
"last_updated": "2021-03-19T10:48:04.057775Z",
"ref": "<CUSTOM_RULE_REF>",
"enabled": true
}
],
"last_updated": "2021-03-19T10:48:04.057775Z",
"phase": "http_request_firewall_custom"
},
"success": true,
"errors": [],
"messages": []
}

The example uses the url_decode() function because fields in the request body (available in http.request.body.form) are URL-encoded when the content type is application/x-www-form-urlencoded.

After creating a custom ruleset, deploy it to a phase so that it executes. Refer to Deploy a custom ruleset for more information.

​​ Example B

This POST request example creates a new custom ruleset with a rule that checks for exposed credentials in JSON responses. The rule has a match if both the rule expression and the exposed_credential_check result are true. When there is a match, the rule will add an Exposed-Credential-Check HTTP header to the request with value 1.

curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/rulesets" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{
"name": "Custom Ruleset B",
"kind": "custom",
"description": "This ruleset includes a rule checking for exposed credentials.",
"rules": [
{
"action": "rewrite",
"action_parameters": {
"headers": {
"Exposed-Credential-Check": {
"operation": "set",
"value": "1"
}
}
},
"description": "Exposed credentials check on login endpoint with JSON body",
"expression": "http.request.method == \"POST\" && http.request.uri == \"/login.php\" && any(http.request.headers[\"content-type\"][*] == \"application/json\")",
"exposed_credential_check": {
"username_expression": "lookup_json_string(http.request.body.raw, \"username\")",
"password_expression": "lookup_json_string(http.request.body.raw, \"password\")"
}
}
],
"phase": "http_request_firewall_custom"
}'

The response returns the created ruleset. Note the presence of the following elements in the rule definition:

  • The rewrite action.
  • The action_parameters object configuring the HTTP header added to requests with exposed credentials.
  • The exposed_credential_check object.
{
"result": {
"id": "<CUSTOM_RULESET_ID>",
"name": "Custom Ruleset B",
"description": "This ruleset includes a rule checking for exposed credentials.",
"kind": "custom",
"version": "1",
"rules": [
{
"id": "<CUSTOM_RULE_ID>",
"version": "1",
"action": "rewrite",
"action_parameters": {
"headers": {
"Exposed-Credential-Check": {
"operation": "set",
"value": "1"
}
}
},
"description": "Exposed credentials check on login endpoint with JSON body",
"expression": "http.request.method == \"POST\" && http.request.uri == \"/login.php\" && any(http.request.headers[\"content-type\"][*] == \"application/json\")",
"exposed_credential_check": {
"username_expression": "lookup_json_string(http.request.body.raw, \"username\")",
"password_expression": "lookup_json_string(http.request.body.raw, \"password\")"
},
"last_updated": "2022-03-19T12:48:04.057775Z",
"ref": "<CUSTOM_RULE_REF>",
"enabled": true
}
],
"last_updated": "2022-03-19T12:48:04.057775Z",
"phase": "http_request_firewall_custom"
},
"success": true,
"errors": [],
"messages": []
}

​​ Next steps

After creating a custom ruleset, deploy it to the http_request_firewall_custom phase at the account level so that it executes. You will need the ruleset ID to deploy the custom ruleset. For more information, refer to Deploy a custom ruleset.