# Bot Manager Lite

Bot Manager Lite is the self-serve edition of [Bot Manager](/en/documentation/platform/firewall/#bot-manager), installed from Azion Marketplace and run as a function instance on a [Firewall](/en/documentation/platform/firewall/). The installed function is version `0.2.0`, it is written in JavaScript, and it takes its whole configuration from one JSON arguments object.

The function scores each request against 26 static rules. Every rule a request matches adds a fixed number of points, and when the total reaches or passes the `threshold` argument the function applies the `action` argument. A request that stays below the threshold continues through the [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine/) to the application. The rules score the shapes left by scraping and brute force clients: an absent user agent, an absent `Accept-Language` header, a session cookie that does not verify.

This page lists the 26 rules with their IDs, scores, and classes, the arguments the function ships a default for, and the report log it writes.

---

## Rules

Each rule below adds its score increment to the request's running total, and the class names the behavior the rule scores. A rule whose ID is listed in the `disabled_rules` argument is not processed and adds nothing.

| ID | What it matches                                                                           | Score | Class                      |
| -- | ----------------------------------------------------------------------------------------- | ----- | -------------------------- |
| 1  | `${http_user_agent}` is empty                                                             | 8     | Bad bot signatures         |
| 2  | `${http_content_type}` is empty and `${request_body}` is not empty                        | 8     | Bad bot signatures         |
| 3  | `${http_referer}` is empty and `${request_method}` is `POST`, `PUT`, `PATCH`, or `DELETE` | 6     | Malicious intent           |
| 4  | `${http_user_agent}` contains the string `Dalvik`                                         | 4     | Bad bot signatures         |
| 5  | `${http_user_agent}` contains the string `Trident`                                        | 6     | Bad bot signatures         |
| 6  | `${http_user_agent}` contains the string `Headless`                                       | 6     | Bad bot signatures         |
| 7  | `${http_user_agent}` is longer than 200 characters or shorter than 10 characters          | 4     | Bad bot signatures         |
| 8  | `${http_user_agent}` matches a known bad bot user agent                                   | 8     | Scripted bots              |
| 9  | `${http_accept}` is empty                                                                 | 8     | Bad bot signatures         |
| 10 | `${http_accept_language}` is empty                                                        | 8     | Bad bot signatures         |
| 11 | `${http_range}` is empty                                                                  | 6     | Malicious intent           |
| 12 | `${request_method}` is `TRACE`                                                            | 8     | Malicious intent           |
| 13 | `${http_content_length}` is empty and `${request_method}` is `POST`, `PUT`, or `PATCH`    | 8     | Bad bot signatures         |
| 14 | The client IP is found in a reputation Network List                                       | 6     | Reputation Intelligence    |
| 15 | `${request_method}` is `POST`, `PUT`, or `PATCH` and `${cookie_az_botm}` is absent        | 8     | Malicious browser behavior |
| 16 | `${request_method}` is `POST`, `PUT`, or `PATCH` and `${cookie_az_asm}` is absent         | 8     | Malicious browser behavior |
| 17 | The session cookie integrity check fails                                                  | 16    | Malicious browser behavior |
| 18 | `${http_sec_fetch_mode}` is empty                                                         | 4     | Malicious intent           |
| 19 | `${http_sec_fetch_dest}` is empty                                                         | 4     | Malicious intent           |
| 20 | `${http_sec_fetch_site}` is empty                                                         | 4     | Malicious intent           |
| 21 | `${server_fingerprint}` matches an entry in `bad_fingerprint_list`                        | 32    | Malicious browser behavior |
| 22 | `${http_user_agent}` matches a known outdated browser user agent                          | 6     | Bad bot signatures         |
| 23 | `${server_protocol}` is `HTTP/1.0` or `HTTP/1.1`                                          | 6     | Scripted bots              |
| 24 | `${geoip_asn}` matches a known cloud provider ASN                                         | 4     | Cloud provider             |
| 25 | `${http_user_agent}` matches a known headless browser user agent                          | 4     | Bad bot signatures         |
| 26 | `${http_user_agent}` matches a known scripted client user agent                           | 8     | Bad bot signatures         |

> **Note**
>
> Rules 15, 16, and 17 read the session cookie pair the function sets on a browser, `az_botm` and `az_asm`. For more information, refer to [Bot scoring](/en/documentation/platform/firewall/bot-manager/bot-scoring/#session-cookies).

Rule 14 checks the client IP against the [Network Lists](/en/documentation/platform/firewall/network-shield/network-lists/) whose IDs are listed in `reputation_network_lists`, and adds 6 points for each list the IP is found in.

Two arguments take a request out of the table before it is scored. A request whose fingerprint is listed in `good_fingerprint_list` bypasses every rule above. With `block_ai_bots` set to `true`, a request from a known AI user agent is blocked upstream of the scoring pipeline, so it reaches no rule and carries no rule IDs in its log line.

> **Caution**
>
> Rules 18 to 26 ship in v0.2.0 without prior calibration, so they can score legitimate traffic depending on your traffic profile. Run the instance with `action` set to `allow`, read the rule IDs out of the report log, and list the rules that keep matching legitimate requests in `disabled_rules` before you move to a blocking action.

The IDs a request matched are written to the report log, so the values for `disabled_rules` come from your own traffic rather than from this table.

---

## Arguments

A Bot Manager Lite instance takes its whole configuration from one JSON object, and no argument is required. Azion Console renders the object as the **Arguments** section of a function instance, under the firewall's **Functions Instances** tab, and the Azion API and the Azion CLI carry it as `args`. The installed function publishes no argument schema, so the **Arguments** editor has no form to build from one and the object is written as raw JSON.

Nothing checks that object. Every key an instance carries is stored and read back exactly as it was sent, including a key the function never reads. Write `thresold` in place of `threshold` and the instance keeps `thresold`, the function keeps scoring against `30`, and no interface reports a problem. An argument reaches the function only under the name the function reads.

The shipped defaults are a runtime fallback rather than a copy. An instance created with `{}` stores `{}`, so reading an instance tells you which arguments that instance sets, not the values the function runs at.

Bot Manager Lite v0.2.0 ships a default for eight arguments:

| Argument                | Type             | Default                | What it does                                                                                                                                                                   |
| ----------------------- | ---------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `action`                | string           | `deny`                 | What the function does with a request at or above the threshold. The seven values are listed in [Arguments](/en/documentation/platform/firewall/bot-manager/arguments/#action) |
| `bad_fingerprint_list`  | array of strings | `[]`                   | The fingerprints rule 21 scores against, at 32 points for a match                                                                                                              |
| `disabled_rules`        | array of numbers | `[]`                   | The rule IDs the function does not process. A disabled rule adds nothing to the score                                                                                          |
| `good_fingerprint_list` | array of strings | `[]`                   | The fingerprints that skip the rule table entirely                                                                                                                             |
| `internal_logs`         | number           | `0`                    | Which requests the function writes a report log line for. The four values are listed below                                                                                     |
| `log_headers`           | array of strings | The nine headers below | The request headers the function writes into the report log                                                                                                                    |
| `log_tag`               | string           | `bot-manager-instance` | The tag that identifies the instance in the report log. Give each instance its own tag                                                                                         |
| `threshold`             | number           | `30`                   | The score a request reaches before `action` fires. A lower value acts on more requests, a higher value on fewer                                                                |

`log_headers` ships with nine headers: `accept`, `accept-encoding`, `accept-language`, `content-type`, `host`, `referer`, `user-agent`, `x-forwarded-for`, and `x-request-id`. The array names the headers the function does write, not headers to keep out of the log. Seven headers are never written, whatever the array carries: `authorization`, `cookie`, `proxy-authorization`, `set-cookie`, `x-csrf-token`, `x-api-key`, and `x-amz-security-token`. Header values are written base64-encoded.

The seven arguments below are documented for Bot Manager Lite and ship no default with the function, so **Documented default** is the value the documentation states rather than a value read off the installed function.

| Argument                    | Type             | Documented default | What it does                                                                                                 |
| --------------------------- | ---------------- | ------------------ | ------------------------------------------------------------------------------------------------------------ |
| `block_ai_bots`             | boolean          | `false`            | Blocks a request from a known AI user agent before the scoring rules run                                     |
| `custom_html`               | string           | —                  | The HTML the `custom_html` action returns. Absent, or not a string, the function runs `allow`                |
| `custom_status_code`        | number           | `200`              | The status code the `custom_html` response carries. Absent, or not a number, it is `200`                     |
| `redirect_to`               | string           | —                  | The URL the `redirect` action sends the request to. Absent, or not a string, the function runs `allow`       |
| `reputation_network_lists`  | array of numbers | `[]`               | The Network List IDs rule 14 checks the client IP against, at 6 points for each matched list                 |
| `session_signature_key`     | string           | `az`               | The HMAC key that signs the `az_asm` session cookie. Absent, or invalid, the function uses `az`              |
| `should_write_warning_logs` | boolean          | `false`            | Whether the function writes warning logs to [Real-Time Events](/en/documentation/platform/real-time-events/) |

Bot Manager documents further arguments that Bot Manager Lite does not, and the values `action` accepts are listed once for both editions. For more information, refer to [Arguments](/en/documentation/platform/firewall/bot-manager/arguments/).

### Internal logs

`internal_logs` selects which requests the function writes a report log line for. A value the function does not recognize is read as `0`.

| Value | What the function logs                                                     |
| ----- | -------------------------------------------------------------------------- |
| `0`   | A request whose score is above `0`. This is the default                    |
| `1`   | A request whose score is above `0`, and a request classified as a good bot |
| `2`   | Every request                                                              |
| `3`   | No request                                                                 |

Set `internal_logs` to `2` while you calibrate an instance. A request that scored `0` then still produces a line, which is the only way to see that the rules ran and matched nothing.

---

## Report log

Bot Manager Lite writes one line per scored request. The line opens with the product and the
instance's `log_tag` in brackets, then carries a JSON object of fourteen fields:

```text
[Bot-Protection][storefront-bots] Report:  {"request_id":"0123456789abcdef0123456789abcdef","remote_addr":"203.0.113.42","fingerprint":"ge20cn020000_000000000000_000000000000_000000000000","host":"<your-workload-domain>","http_user_agent":"","request_uri":"/","geoip_country":"BR","geoip_region":"SP","asn":"64496","score":28,"bot_category":"Bad Bot Signatures, Malicious Intent detected","classified":"legitimate","action":"allow","matched_rules":[1,10,18,19,20]}
```

The `log_tag` sits in the **prefix**, not in the object, so a firewall running several instances is
told apart by the bracket rather than by a field. The object carries `request_id`, `remote_addr`,
`fingerprint`, `host`, `http_user_agent`, `request_uri`, `geoip_country`, `geoip_region`, `asn`,
`score`, `bot_category`, `classified`, `action`, and `matched_rules`. Bot Manager writes a longer
object; the field dictionary for both is on [Logs](/en/documentation/platform/firewall/bot-manager/logs/#fields).

`score` is the request's cumulative total across every rule it matched, and `matched_rules` carries
the IDs that fired — which is where the values for `disabled_rules` come from. The two agree with
the table above: the line shown matched rules 1, 10, 18, 19, and 20, whose increments of 8, 8, 4, 4,
and 4 sum to the `score` of 28.

`bot_category` is a comma-joined list of the classes of the rules that matched, not a single value:
rules 1 and 10 are `Bad bot signatures` and rules 18, 19, and 20 are `Malicious intent`.

`classified` is a verdict relative to the threshold rather than a property of the request on its
own. The same score of 28 from the same rules reads `legitimate` under a threshold of 30 and
`bad bot` under a threshold of 1. Raising a threshold stops the action from firing and
changes how the traffic is labelled in the logs.

`geoip_country` carries a country code, and `fingerprint` carries four underscore-separated
segments rather than a single hash. `request_id` correlates the line with the same request in
Azion's other observability tools, and `remote_addr` is the client IP that rule 14 checks against
the reputation lists.

---

## Related resources

- [Firewall best practices](/en/documentation/platform/firewall/best-practices.md#bot-manager): How to calibrate the threshold and the disabled rules against your own traffic.
- [Install Bot Manager Lite](/en/documentation/guides/application-development/integrations/bot-manager-lite.md): Installs the function, instances it on a firewall, and calls it from a rule.
- [Test Bot Manager Lite with the Starter Kit](/en/documentation/guides/application-development/frameworks/bot-manager-lite-starter-kit.md): Deploys a sample application with the function already instanced against it.
- [Add Bot Manager Lite to a Firewall](/en/documentation/guides/application-development/integrations/bot-manager-lite-integration-kit.md): Adds the function to a firewall that already protects an application.
