> This page is for Applications Protection.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.humansecurity.com/llms.txt.

# Configuration (v5 and Below)

The HUMAN Enforcer is configured using a set of properties specified in the `custom/pxConfig.json\` file. A minimal valid configuration file looks as follows:

**`Title=`**

```text Title="From v4.0.0"
//pxConfig.json
{
    px_app_id: 'APP_ID',
    px_auth_token: 'AUTH_TOKEN',
    px_cookie_secret: 'COOKIE_SECRET',
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
//pxConfig.json
{
    appId: 'APP_ID',
    authToken: 'AUTH_TOKEN',
    cookieKey: 'COOKIE_SECRET',
};
```

In addition, the following set of properties is available:

## Is Bot Enforcer

A boolean flag to configure the enforcer as Bot Defender enforcer

**Default:** true

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_bot_enforcer: true
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 isBotEnforcer: true
 ...
};
```

## Is Code Enforcer

A boolean flag to configure the enforcer as Code Defender enforcer

**Default:** false

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_code_enforcer: false
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 isCodeEnforcer: false
 ...
};
```

## Module Enabled

A boolean flag to enable/disable the HUMAN Enforcer.

Default: true

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_module_enabled: true
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 moduleEnabled: true
 ...
};
```

## Module Mode

Sets the working mode of the worker.

Possible values:

* `monitor` - Monitor Mode
* `active_blocking` - Blocking Mode

From v4.0.0 - A string that sets the working mode of the worker.\
**Default:** `monitor` (from v4.0.0)

Up to v3.3.0 - 0/1 numeric value which sets the working mode of the worker (0 - monitor mode, 1 - active blocking mode)\
**Default:** 0 (up to v3.3.0)

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_module_mode: 'monitor'
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 moduleMode: 0
 ...
};
```

## Blocking ScoreSets the minimum blocking score of a request.

Possible values:

* Any integer between 0 and 100.

**Default:** 100

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_blocking_score: 100
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 blockingScore: 100
 ...
};
```

## Cross-Origin Resource Sharing (CORS) Support

For security reasons, browsers can block cross-origin requests, if they are not allowed by a third-party origin.

CORS is a mechanism that lets the server indicate, if a request contains cross-origin resources. It does so by adding special HTTP headers to the request, which allows the browser to load such resources.

In most cases, CORS employs a two-stage procedure with a preliminary request, called preflight, followed by the actual request. The preflight request checks if the actual request will be responded to. To learn more about different request types, see these [examples](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Examples_of_access_control_scenarios).

The CORS behavior must be configured to address both simple requests (without preflight) and more complex ones (with preflight).

Use the following Enforcer functions to configure CORS:

| Function                                       | Default Value | Description                                                                                                                                     |
| ---------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `px_cors_support_enabled`                      | false         | Set to true to enable CORS support.                                                                                                             |
| `px_cors_create_custom_block_response_headers` | null          | Define here custom headers to be added to the block response. Required for simple request. If not configured, default settings will be applied. |
| `px_cors_preflight_request_filter_enabled`     | false         | Set to true to let the Enforcer pass preflight requests to the origin.                                                                          |
| `px_cors_custom_preflight_handler`             | null          | Define here a custom handler that will allow the Enforcer to respond to preflight requests immediately without passing them to the origin.      |

Default block response headers settings:

```javascript
return [{ name: 'Access-Control-Allow-Origin', value: request.headers.get('Origin')},
        { name: 'Access-Control-Allow-Credentials', value: 'true' }
}
```

Here’s an **example** of how to configure your Enforcer using these functions:

```javascript
const pxConfig = {
  ...
  px_cors_support_enabled: true
  ...
};
px_cors_create_custom_block_response_headers: (request) => {
   return [{ name: 'Access-Control-Allow-Origin', value: request.headers.get('Origin')},
           { name: 'Access-Control-Allow-Credentials', value: 'true' },
           { name: 'Access-Control-Allow-Methods', value: 'GET, POST, OPTIONS' },
           { name: 'Access-Control-Allow-Headers', value: 'Content-Type, Authorization' }];
}

const pxConfig = {
  ...
  px_cors_preflight_request_filter_enabled: true
  ...
};
px_cors_custom_preflight_handler: (request) => {
   const responseHeaders = {
      'Access-Control-Allow-Origin': request.headers.get('Origin'),
      'Access-Control-Allow-Methods': request.headers.get('Access-Control-Request-Method'),
      'Access-Control-Allow-Headers': request.headers.get('Access-Control-Request-Headers'),
      'Access-Control-Allow-Credentials': 'true',
      'Access-Control-Max-Age': '86400',
   };
   return new Response(null, { headers: responseHeaders, status: 204 });
}
```

## Debug Mode

**From v4.0.0**\
Sets the logging mode of the worker.

Possible values:

* `none` - HUMAN logger will not output any logs
* `error` - HUMAN logger will log errors only and fatal events (e.g., exceptions)
* `debug` - HUMAN logger will output detailed logs for debugging purposes

Be aware that log messages are present in your worker's *logs* tab in Cloudflare's dashboard\
**Default:** `error`

**Up to v3.3.0**\
A flag that configures the enforcer in debug mode, so that the logger will output detailed logs for debugging purposes.

**Default:** false

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_logger_severity: `error`
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 debugMode: false
 ...
};
```

## Send Async Activities

A boolean flag to enable or disable sending of activities and metrics to HUMAN on each request. Enabling this feature will provide data that populates the HUMAN portal with valuable information, such as the number of requests blocked and additional API usage statistics.

**Default:** true

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_send_async_activities_enabled: true
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 sendPageActivities: true
 ...
};
```

## S2S Timeout

The maximum amount of time, in milliseconds, to wait when performing a Risk API request. If this timeout is reached before a score is obtained, the request will pass with `pass_reason: s2s_timeout`.

**Default**: 1000

```javascript
const pxConfig = {
 ...
 px_s2s_timeout: 2000,
 ...
};
```

## Sensitive Routes

An array of route prefixes and/or regular expressions that trigger a server call to HUMAN servers every time the page is viewed, regardless of viewing history.

**Default:** Empty array

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_sensitive_routes: ['/login', /\/user\/.*\/checkout/]
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 sensitiveRoutes: ['/login', '/user/checkout']
 ...
};
```

## Sensitive Headers

An array of headers that are not sent to HUMAN servers on API calls.

**Default:** \['cookie', 'cookies']

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_sensitive_headers: ['cookie', 'cookies', 'x-sensitive-header']
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 sensitiveHeaders: ['cookie', 'cookies', 'x-sensitive-header']]
 ...
};
```

## IP Headers

An array of trusted headers that specify an IP to be extracted. If the array is empty, the default IP header `cf-connecting-ip` is used.

**Default:** Empty array

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_ip_headers: ['x-user-real-ip']
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 px_ip_headers: ['x-user-real-ip']
 ...
};
```

## First Party Enabled

A boolean flag to enable or disable first-party mode.

**Default:** true

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_first_party_enabled: false
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 firstPartyEnabled: false
 ...
};
```

## Filter By Extension

An array of extensions that are always filtered and not validated by the HUMAN Enforcer. Requests with path extensions matching these configured patterns will always be allowed to pass the HUMAN Enforcer. Extensions written with or without periods (e.g., `.css` or `css`) are equivalent.

**Default:** \['.css', '.bmp', '.tif', '.ttf', '.docx', '.woff2', '.js', '.pict', '.tiff', '.eot', '.xlsx', '.jpg', '.csv', '.eps', '.woff', '.xls', '.jpeg', '.doc', '.ejs', '.otf', '.pptx', '.gif', '.pdf', '.swf', '.svg', '.ps', '.ico', '.pls', '.midi', '.svgz', '.class', '.png', '.ppt', '.mid', '.webp', '.jar', '.json', '.xml']

```javascript
const pxConfig = {
  ...
  px_filter_by_extension: ['html', 'css', 'js', 'jpg'],
  ...
};
```

## Filter By HTTP Method

An array of strings that represent HTTP methods that are always filtered and not validated by the HUMAN Enforcer.\
Requests with HTTP methods matching these will always be allowed to pass the HUMAN Enforcer.

**Default:** `[]`

```javascript
const pxConfig = {
  ...
  px_filter_by_extension: ['DELETE'],
  ...
};
```

## Filter By Route

An array of route prefixes and/or regular expressions that are always filtered out and not validated by the HUMAN Enforcer. Requests with paths matching these configured patterns will always be allowed to pass the HUMAN Enforcer.

A regular expression can be defined using `new RegExp` or directly as an expression, and will be treated as is. A string value of a path will be treated as a prefix.

> 📘 Note
>
> This feature was called "whitelisted URIs" in previous versions.

**Default:** Empty

**`Title=`**

```text Title="From v5.0.0"
const pxConfig = {
  ...
  px_filter_by_route: ['/contant-us', /\/user\/.*\/show/]
  ...
};
```

**`Title=`**

```Text Title="Up to v4.5.4"
const pxConfig = {
  ...
  px_whitelist_uri_full: ['/contant-us', /\/user\/.*\/show/]
  ...
};
```

## Enforced Specific Routes

Use this feature to define an array of route prefixes/regular expressions to be enforced in the Monitor mode.

You may want certain requests to be enforced by HUMAN, even when the Enforcer is in the Monitor mode. Requests for predefined route prefixes (example: /profile/user/test) and/or regular expressions (example: /profile.\*) will go through the full enforcement workflow, and may be blocked based on their score.

**Default:** Empty array

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
  ...
  px_enforced_routes: ['/home',/^\/$/

                      ]
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
  ...
  enforcedSpecificRoutes: ['/home',/^\/$/]
  ...
};
```

## Monitored Specific Routes

An array of route prefixes and/or regular expressions that are always set to be in the [Monitor mode](/applications/cloudflare-config#px_module_mode). This only takes effect when the module is enabled and in blocking mode. A regular expression can be defined using `new RegExp` or directly as an expression, and will be treated as is. A string value of a path will be treated as a prefix.

**Default:** Empty array

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
  ...
  px_monitored_routes: ['/home', /^\/$/]
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
  ...
  monitoredSpecificRoutes: ['/home', /^\/$/]
  ...
};
```

## Custom Verification Handler

A JavaScript function that adds a custom response handler to the request.

**Default:** null

**`Title=`**

```text Title="From v4.0.0"
module.exports = {
  ...
    px_custom_verification_handler: (pxCtx, request) => {
      ...
      return {body: result, status: 200, statusDescription: "OK", header: {key: 'Content-Type', value:'application/json'}};
    },
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
module.exports = {
  ...
    customVerificationHandler: (pxCtx, request) => {
      ...
      return {body: result, status: 200, statusDescription: "OK", header: {key: 'Content-Type', value:'application/json'}};
    },
  ...
};
```

## PX Context Object (pxCtx)

pxCtx is an internal object within the Enforcer, which is created per request and holds the entire state regarding the specific request. The customer who integrates the Enforcer in his environment controls the Enforcer behavior using different configuration values, a few of them are custom functions the customer can implement as necessary.\
One of the parameters for those custom functions is the pxCtx, which can be used to access fields and values that the Enforcer has inferred from the request as part of its detection process, and can be used by the customer to perform his own logic based on our detections.\
A simple use case for example is to examine the px score that the request gets and add a header to the request to the origin with the given score.

The functions that has access to the pxCtx are:

* Additional Activity Handler
* Enrich Custom Parameters
* Custom Verification Handler (only exists in Cloudflare) - A function that adds a custom\
  response handler to the request, in case you want to respond differently on some requests.

#### pxCtx useful fields:

* **score** - the PX score this request received.
* **riskRtt** - risk round trip time, the time it took for the risk request from when it was sent util the response was received.
* **pxde** - PX data enrichment, the data enrichment cookie is attached to S2S calls as a way to transfer additional data between the Enforcer and HUMAN collector. The data it contains is set by the collector according to the setting in the portal and is available on the cookie as a JSON object. While this functionality is mostly controlled by the collector, you may want access to the PXDE values after activities have been sent, in the additional activity handler.
* **passReason**- the reason PX decided to pass the request, can be one of:
  * s2s
  * cookie
  * s2s\_timeout
  * s2s\_error
* **isMobile** - whether this is a mobile or web request.
* **httpMethod** - the request’s http method.
* **ip** - the ip of the request as the Enforcer concluded.
* **additionalFields** - holds login credentials (hashed) and graphQL related information

## Additional Activity Handler

A JavaScript function that allows interaction with the request data collected by HUMAN before the data is returned to the HUMAN servers. This function must be set in the `custom/pxCustomFunctionsConfig.js` file.

**Default:** null

**`Title=`**

```text Title="From v4.0.0"
module.exports = {
  ...
    px_additional_activity_handler: (pxCtx, config) => {
      const dataEnrichmentObject = pxCtx.pxde;
      const isDataEnrichmentVerified = pxCtx.pxdeVerified;
      ...
    },
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
module.exports = {
  ...
    additionalActivityHandler: (pxCtx, config) => {
      const dataEnrichmentObject = pxCtx.pxde;
      const isDataEnrichmentVerified = pxCtx.pxdeVerified;
      ...
    },
  ...
};
```

## Enrich Custom Parameters

With the `px_enrich_custom_parameters` function you can add up to 10 custom parameters to be sent back to HUMAN servers. When set, the function is called before setting the payload on every request to HUMAN servers. The parameters should be passed according to the correct order (1-10) and their format must align as following: `custom_param1, custom_param2, ... , custom_param10`. The parameters passed along with the `px_enrich_custom_parameters` function are `request` which is the Cloudflare [request object](https://developers.cloudflare.com/workers/runtime-apis/request), and `pxCtx` which is a HUMAN object.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
module.exports = {
  ...
    px_enrich_custom_parameters: async (pxCtx, request) => {
      let customParams = {};
      customParams["custom_param1"] = "yay, test value";
      // ...
      return customParams;
    },
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
module.exports = {
  ...
    enrichCustomParameters: async (pxCtx, request) => {
      let customParams = {};
      customParams["custom_param1"] = "yay, test value";
      // ...
      return customParams;
    },
  ...
};
```

## Hype Sale Challenge

The enforcer will serve a hype sale challenge for any request that is marked as a hype sale. To mark a request as hype sale add a [custom parameter](/applications/set-custom-parameters) with the key `is_hype_sale` and a boolean value of true. Since marking the request is in the enrich custom param method, the mark can be upon request parameters, context parameters, or any other logic or global variables (environment variables or KV)

for example, the following snippet will initiate hype sale challenge for a request which contains query param 'id' with the value 111:

**`Title=`**

```text Title="From v4.0.0"
module.exports = {
  ...
    px_enrich_custom_parameters: async (pxCtx, request) => {
      const { searchParams } = new URL(request.url);
            if (searchParams.has("id")){
                let id = searchParams.get('id');
                return {
                    "is_hype_sale" : id === '111'
                    }
            }
            return {};
    },
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
module.exports = {
  ...
    enrichCustomParameters: async (pxCtx, request) => {
      const { searchParams } = new URL(request.url);
            if (searchParams.has("id")){
                let id = searchParams.get('id');
                return {
                    "is_hype_sale" : id === '111'
                    }
            }
            return {};
    },
  ...
};
```

## CSS Ref

Modifies a custom CSS by adding the `px_css_ref` directive and providing a valid URL to the CSS.

**Default:** Empty

**`Title=`**

```text Title="Up to v3.3.0"
const pxConfig = {
  ...
  cssRef: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'
  ...
};
```

**`Title=`**

```Text Title="From v4.0.0"
const pxConfig = {
  ...
  px_css_ref: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'
  ...
};
```

## JS Ref

Adds a custom JS file by adding `px_js_ref` directive and providing the JS file that is loaded with the block page.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_js_ref: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 jsRef: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'
 ...
};
```

## Custom Logo

The logo is displayed at the top of the block page.\
Max-height = 150px, Width = auto.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_custom_logo: 'https://s.perimeterx.net/logo.png',
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 customLogo: 'https://s.perimeterx.net/logo.png',
 ...
};
```

#### Filter Traffic by User Agent

An array of user agents that are always filtered and not validated by the HUMAN Enforcer.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_filter_by_user_agent: ['testUserAgent/v1.0']
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 filterByUserAgent: ['testUserAgent/v1.0']
 ...
};
```

## Filter Traffic by IP

An array of IP ranges / IP addresses that are always filtered and not validated by the HUMAN Enforcer.

**Default:** Empty array

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_filter_by_ip: ['192.168.10.0/24', '192.168.2.2']
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 filterByIP: ['192.168.10.0/24', '192.168.2.2']
 ...
};
```

## Filter Traffic by header

An object consists of *headerName*: *headerValue* pairs that are always filtered and not validated by the HUMAN Enforcer.

**Default:** Empty

From v4.0.3

```text
const pxConfig = {
 ...
 px_filter_by_header: {
    test_header: "true",
    goodBot: "abc"
 }
 ...
};
```

## Custom Cookie Header

Allows to set a header name which is used to extract theHUMAN cookies (processed in addition to the Cookie header).

**Default**: "x-px-cookies"

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_custom_cookie_header: "x-px-cookies"
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 customCookieHeader: "x-px-cookies"
 ...
};
```

## Upstream Score Header

When set, this property specifies a header name that will contain the HUMAN score to be sent to the origin.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
 px_score_header_name: "x-px-score"
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
 scoreHeaderName: "x-px-score"
 ...
};
```

## Upstream Identifier Header

When set, this property specifies a header name that will contain the HUMAN unique identifier (UUID) to be sent to the origin.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
 ...
     px_identifier_header_name: "x-px-uuid"
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
 ...
     identifierHeaderName: "x-px-uuid"
 ...
};
```

## Login Credentials Extraction

This feature extracts credentials (hashed username and password) from requests and sends them to HUMAN as additional info in the risk api call. The feature can be toggled on and off and may be set for any number of unique paths. The settings are adjusted by modifying the `custom/pxConfig` JSON object.\
If credentials are found to be compromised, the header `px-compromised-credentials` will be added to the origin request with the value `1`. You may configure the name of this header with the `px_compromised_credentials_header` configuration.

**Default Values**

* px\_compromised\_credentials\_header: "px-compromised-credentials"
* px\_login\_credentials\_extraction\_enabled: false
* px\_login\_credentials\_extraction: \[]

From v4.0.0

```text
const pxConfig = {
  ...
  px_compromised_credentials_header: "x-px-comp-creds",
  px_login_credentials_extraction_enabled: true,
  px_login_credentials_extraction: [
    {
      path_type: "exact" or "regex" // default: exact
      path: "/login", // support regular expressions and exact path configuration
      method: "post", // supports all http methods
      sent_through: "body", // supported sent_throughs: body, header, query-param
      pass_field: "password", // name (or array of names) of the password field in the request (can also be nested field using dots i.e details.password)
      user_field: ["username", "email"] // name (or array of names) of the username field in the request (can also be nested field using dots i.e details.username)
    },
    ...
  ],
  ...
};
```

> **Note**
>
> Define regular expression "path": When using path\_type "regex" the path attribute should contain regular expression as a string pattern without slashes and without flags (i.e, instead of /ab+c/i configure "ab+c"). Regular expressions are treated as case-insensitive by the enforcer by default.

Configure `user_field` or `pass_field` as an array when the same login endpoint can have two or more different field names as input.

It is also possible to define a custom callback to extract the username and password. The function should accept the request object as a parameter and return an object with the keys `user` and `pass`. If extraction is unsuccessful, the function should return `null`.

From v4.0.0

```text
const pxConfig = {
    ...
    px_login_credentials_extraction_enabled: true,
    px_login_credentials_extraction: [{
        path: "/login",
        method: "post",
        callback: (req) => {
            // custom implementation extracting the username and password, e.g.:
            const { username, password } = await req.pxCtx.getRequestBody(req);
            if (username && password) {
                return { user: username, pass: password };
            } else {
                return null;
            }
        }
    }]
};
```

> **Note**
>
> Reading the request body in Cloudflare may increase the request handling time. Since the HUMAN Enforcer may need to read the request body for various operations, we recommend that custom functions retrieve the request body using await request.pxCtx.getRequestBody(request). If the body has already been read and parsed, it will return immediately without needing to clone the request and parse the body a second time. If the body has not already been read, it will save the parsed body in the pxCtx object so that subsequent invocations will not need to clone or parse the body.

### Multistep Login

In some site architectures, the username and password are sent on different HTTP requests. In this case, all relevant paths should be configured as credentials extraction endpoints, and the configuration value `px_credentials_intelligence_version` should be set as `multistep_sso`. (There is no other need to change this configuration value.)

**Default**: v2

From v4.4.0

```text
const pxConfig = {
    ...
  px_credentials_intelligence_version: "multistep_sso",
  px_login_credentials_extraction: [
    {
      path: "/login/username",
      method: "post",
      sent_through: "body",
      pass_field: "none",
      user_field: "username"
    },
    {
      path: "/login/password",
      method: "post",
      sent_through: "body",
      pass_field: "password",
      user_field: "none"
    },
  ],
  ...
}
```

## Additional S2S Activity

To enhance detection on login credentials extraction endpoints, the following additional information is sent to HUMAN via an `additional_s2s` activity:

* **Response Code** - The numerical HTTP status code of the response.
* **Login Success** - A boolean indicating whether the login completed successfully. See the options listed below for how to provide this data.
* **Raw Username** - The original username used for the login attempt. In order to report this information, make sure the configuration `px_send_raw_username_on_additional_s2s_activity` is set to `true`.

### Login Success Reporting[](/applications/cloudflare-config#login-success-reporting)

There are a number of different possible ways to report the success or failure of the login attempt. If left empty, the login successful status will always be reported as `false`.

**Default**: Empty

From v4.4.0

```text
const pxConfig = {
    ...
    px_login_successful_reporting_method: 'status' // supported values: status, header, body, custom
    ...
}
```

**Status**

Provide a status or array of statuses that represent a successful login. If a response's status code matches the provided value or one of the values in the provided array, the login successful status is set to `true`. Otherwise, it's set to `false`.

> **Note**
>
> To define a range of statuses, use the `custom` reporting method.

**Default Values**

px\_login\_successful\_status: 200

From v4.4.0

```text
const pxConfig = {
    ...
    px_login_successful_reporting_method: 'status',
    px_login_successful_status: [200, 202] // number or array of numbers
    ...
}
```

**Header**

Provide a header name and value. If the header exists on the response and matches the provided value, the login successful status is set to `true`. If the header is not found on the response, or if the header value does not match the value in the configuration, the login successful status is set to `false`.

**Default Values**

px\_login\_successful\_header\_name: x-px-login-successful

px\_login\_successful\_header\_value: 1

From v4.2.0

```text
const pxConfig = {
    ...
    px_login_successful_reporting_method: 'header',
    px_login_successful_header_name: 'login-successful',
    px_login_successful_header_value: 'true'
    ...
}
```

**Body**

Provide a string or regular expression with which to parse the response body. If a match is found, the login successful status is set to `true`. If no match is found, the login successful status is set to `false`.

**Default Values**

px\_login\_successful\_body\_regex: Empty

From v4.2.0

```text
const pxConfig = {
    ...
    px_login_successful_reporting_method: 'body',
    px_login_successful_body_regex: 'You logged in successfully!' // string or RegExp
    ...
}
```

**Custom**

Provide a custom callback that returns a boolean indicating if the login was successful.

**Default Values**

px\_login\_successful\_custom\_callback: null

From v4.2.0

```text
const pxConfig = {
    ...
    px_login_successful_reporting_method: 'custom',
    px_login_successful_custom_callback: (response) => {
        // custom implementation resulting in boolean isLoginSuccessful
        return isLoginSuccessful;
    }
    ...
}
```

### Additional S2S Activity Headers

Available from v4.4.0.

Rather than sending the `additional_s2s` activity automatically, it is instead possible to generate the base `additional_s2s` activity along with the URL endpoint, and pass them to the origin server as headers on the original HTTP request. When enabled, the module will add two new headers to the original request and send them to the origin:

* `px-additional-activity`, a stringified JSON activity that should be sent.
* `px-additional-activity-url`, the complete URL endpoint to which the JSON object should be sent.

> Note: Enabling this feature will disable the automatic sending of the `additional_s2s` activity.

**Default Values**

px\_additional\_s2s\_activity\_header\_enabled: false

From v4.2.0

```text
const pxConfig = {
  // ...
  px_additional_s2s_activity_header_enabled: true,
  //...
};
```

The `px-additional-activity` header value is a stringified JSON object that looks like this. Only the fields indicated with `// MODIFY` should be changed prior to sending. Other fields should not be altered in any way.

```json
{
  "type": "additional_s2s",
  "timestamp": 1637000000,
  "socket_ip": "1.1.1.1",
  "px_app_id": "PX_APP_ID",
  "url": "https://www.example.com/the-target-url",
  "vid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "details": {
    "client_uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "request_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "ci_version": "v1",
    "http_status_code": null, // MODIFY, number (e.g., 200, 401, 404, etc.)
    "login_successful": null, // MODIFY, boolean (e.g., true, false)
    "raw_username": null // MODIFY, string (e.g., "test@mail.com")
  }
}
```

After parsing the object and adding the appropriate `http_status_code` and `login_successful` fields in the origin server, send the JSON object as an HTTP `POST` request to the URL provided in the `px-additional-activity-url` header.

> Note: The POST request should be sent with the `Content-Type: application/json` and `Authorization: Bearer <PX_AUTH_TOKEN>` headers.

**Example Origin Server Behavior**

This code provides an example of code at the origin server that handles these headers and performs the API call. The example is in JavaScript, but the process of extracting the `px-additional-activity` and `px-additional-activity-url` headers, modifying the necessary activity fields, and executing the `additional_s2s` XHR request to the HUMAN servers is applicable to all servers for which this feature is enabled, regardless of language.

```javascript
app.post('/login', (req, res) => {
    // complete login flow, resulting in boolean variable isLoginSuccessful
    const responseStatusCode = isLoginSuccessful ? 200 : 401;
    res.sendStatus(responseStatusCode);

    if (req.headers['px-additional-activity'] && req.headers['px-additional-activity-url']) {
        handlePxAdditionalActivity(req, responseStatusCode, isLoginSuccessful);
    }
});

function handlePxAdditionalActivity(req, statusCode, isLoginSuccessful) {
    try {
        // extract url and activity from the request headers
        const url = req.headers['px-additional-activity-url'];
        const activity = JSON.parse(req.headers['px-additional-activity']);

        // change the modifiable values
        activity.details['http_status_code'] = statusCode;
        activity.details['login_successful'] = isLoginSuccessful;

        if (activity.details['credentials_compromised'] && isLoginSuccessful) {
            // add raw username if credentials are compromised and login is successful
            activity.details['raw_username'] = req.body.username;
        } else {
            // remove raw username if login is not successful or credentials are not compromised
            delete activity.details['raw_username'];
        }

        // send the POST request
        axios.post(url, activity, {
            headers: {
                'Authorization': `Bearer ${env.PX_AUTH_TOKEN}`,
                'Content-Type': 'application/json'
            }
        });
    } catch (err) {
        console.error(`Error: ${err}`);
    }
}
```

### Raw Username

When enabled, the raw username used for logins on login credentials extraction endpoints will be reported to HUMAN if (1) the credentials were identified as compromised, and (2) the login was successful as reported via the property above.

**Default**: false

From v4.2.0

```text
const pxConfig = {
    ...
    px_send_raw_username_on_additional_s2s_activity: true
    ...
}
```

## Sensitive GraphQL Operations

For those using GraphQL endpoints, it is possible to trigger server-to-server risk calls on particular operation types or names. Like the sensitive routes feature, a request that contains an operation of the configured type or name will trigger a server call to HUMAN servers every time that operation is performed.

If an operation type (e.g., `query`, `mutation`) is configured in `px_sensitive_graphql_operation_types`, all GraphQL operations of that type will be treated as sensitive. If an operation name is configured in `px_sensitive_graphql_operation_names`, all GraphQL operations with that name will be treated as sensitive.

> Note: This feature only applies to requests that contain the string `graphql` somewhere in the path name.

**Default Values:**

px\_graphql\_enabled: `true`

px\_graphql\_routes: \['/graphql']

px\_sensitive\_graphql\_operation\_types: Empty

px\_sensitive\_graphql\_operation\_names: Empty

From v4.2.0

```text
const pxConfig = {
    ...
    px_graphql_routes: ['/graphql', /^\/(graphql|apiendpoint)$/],
    px_sensitive_graphql_operation_types: ["mutation"],
    px_sensitive_graphql_operation_names: ["LoginOperation", "AccountInfoQuery"]
    ...
};
```

## CSP Support

Add CSP policy header to the response returned to the client (only if active CSP policy exists in HUMAN for the specific appId) - `px_csp_enabled`.

**Default:** false

Invalidates active CSP policy after specified time in minutes where no updates were received from HUMAN - `px_csp_no_updates_max_interval_minutes`.

**Default:** 60

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
  ...
  px_csp_enabled: true,
  px_csp_no_updates_max_interval_minutes: 60
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
  ...
  cspEnabled: true,
  cspNoUpdatesMaxIntervalMinutes: 60
  ...
};
```

## User Identifiers

Enable the extraction of JWT fields from requests and add them to the risk, page requested and block activities.

| **Configuration Name**                 | **Default Value** | **Description**                                                                                                                                                                      |
| -------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `px_jwt_cookie_name`                   | Empty String      | The cookie name that should contain the JWT token.                                                                                                                                   |
| `px_jwt_cookie_user_id_field_name`     | Empty String      | The field name in the JWT object, extracted from the JWT cookie, that contains the user ID to be extracted. This field name can include a path for **a nested object**.              |
| `px_jwt_cookie_additional_field_names` | `[]`              | The field names in the JWT object, extracted from the JWT cookie, that should be extracted in addition to the user ID. These fields' names can include paths for **nested objects**. |
| `px_jwt_header_name`                   | Empty String      | The header name that should contain the JWT token.                                                                                                                                   |
| `px_jwt_header_user_id_field_name`     | Empty String      | The field name in the JWT object, extracted from the JWT header, that contains the user ID to be extracted. This field name can include a path for **a nested object**.              |
| `px_jwt_header_additional_field_names` | `[]`              | The field names in the JWT object, extracted from the JWT header, that should be extracted in addition to the user ID. These fields' names can include paths for **nested objects**. |

\


```json
const pxConfig = {
  ...
    "px_jwt_cookie_name":  "auth",
    "px_jwt_cookie_user_id_field_name": "nameid",
    "px_jwt_cookie_additional_field_names": ["exp", "iss", "user_info.userid"],
    "px_jwt_header_name":  "authorization",
    "px_jwt_header_user_id_field_name": "sub",
    "px_jwt_header_additional_field_names": ["jti, additional.fieldname"]
  ...
};
```

## Pre Enforce Handler

preEnforcerHandler is a function supplied by the customer (supports both synchronous and asynchronous functions) which gets the original request and the request context constructed by HUMAN (pxCtx) and returns an integer value (or a Promise resolved with an integer value) representing one of the following enum values:

* 0 - continue with the request to the regular enforcer flow
* 1 - drop the request and respond with block/captcha page (based on the customer’s policy)

**Default:** null

**`Title=`**

```text Title="From v4.4.0"
module.exports = {
  ...
    px_pre_enforce_handler: (pxCtx, request) => {
      if (request.something) {
          return 1;
      } else {
          return 0;
      }
    },
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
module.exports = {
  ...
    preEnforceHandler: (pxCtx, request) => {
      if (request.something) {
          return 1;
      } else {
          return 0;
      }
    },
  ...
};
```

## Deferred Activities

A boolean flag to enable/disable sending HUMAN page\_requested activity after getting the response from the origin.

**Default:** true

**`Title=`**

```text Title="V 4.0.0"
const pxConfig = {
  ...
  px_deferred_activities: true
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
```

## Test Block Flow on Monitoring Mode

Allows you to test an enforcer’s blocking flow while you are still in Monitor Mode. When the header name is set(e.g., `x-px-block`) and the value is set to `1`, when there is a block response (for example from using a User-Agent header with the value of `PhantomJS/1.0`) the Monitor Mode is bypassed and full block mode is applied. If one of the conditions is missing you will stay in Monitor Mode. This is done per request. To stay in Monitor Mode, set the header value to `0`.

The Header Name is configurable using the `px_bypass_monitor_header` property.

**Default:** Empty

**`Title=`**

```text Title="From v4.0.0"
const pxConfig = {
  ...
  px_bypass_monitor_header: "x-px-block"
  ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
const pxConfig = {
  ...
  bypassMonitorHeader: "x-px-block"
  ...
};
```

## Snippet Injection

A boolean flag to enable/disable injection of the JavaScript sensors snippet into site pages. The snippet will be added to the end of the `<head>` element.

**Default**: false

**`Title=`**

```text Title="From v4.1.0"
const pxConfig = {
 ...
 px_snippet_provider_enabled: true
 ...
};
```

**`Title=`**

```Text Title="Up to v4.0.0"
const pxConfig = {
 ...
 px_sensor_inject_enabled: true
 ...
};
```

**`Title=`**

```Text Title="Up to v3.3.0"
```

`px_snippet_provider_cache_ttl_seconds` determines how long will the snippet retrieved from HUMAN servers will be held in the cache. After the specified time period the enforcer will attempt to retrieve the snippet again from the HUMAN servers.

**Default**: 600

From v4.1.0

```text
const pxConfig = {
 ...
 px_snippet_provider_cache_ttl_seconds: 600
 ...
};
```

> **Note**
>
> When enabling the Snippet injection feature, do not forget to address the [First Party Enabled](/applications/cloudflare-config#first-party-enabled) configuration.
>
> Defining the content of the snippet to be injected to the HTML response is done internally via HUMAN operations team. To do so please get in touch with your HUMAN contact person or contact support [here](/applications/support).

## Custom sensitive request

Allows writing your own logic to decide whether the request is sensitive.

The custom sensitive request function gets the request object as a parameter and should return true, otherwise, return false. Throwing an exception is equivalent to \`false\`. Implementing this configuration does not override other \`sensitive\` configurations, like \`sensitive\_routes\`.

Example:

```javascript
px_custom_is_sensitive_request = async (request) => {
   const url = new URL(request.url);
   if (request.method === 'POST' && url.pathname === '/test') {
         const req = request.clone();
         let body = await req.json();
         if (body && body.specificField) {
            return true;
          }
   }
   return false;
}
```

> **Note**
>
> For reading the request body, it's mandatory to create a copy of the request object (by using the \`clone()\` function and read the body from the cloned request.

## Enforcer Timeout

By default, the Enforcer is set to timeout after 1000 ms. If you wish to change the value of the timeout, set the desired value of the `ENFORCE_TIMEOUT` property in your `workerBundle.js` file.

```javascript
...
ENFORCE_TIMEOUT = 2000 // sets the timeout to 2000ms
...
```

## Sign Cookie with IP

By default, cookies are signed with user agent only; however, it is possible to sign cookies with the socket IP as well. In order to enable cookie signing with the socket IP, ensure that the socket IP is extracted properly using the `px_ip_headers` configuration and reach out to your HUMAN representative.