Under Attack Mode (UAM)
Overview
Under Attack Mode (UAM) is a WebShield feature that lets a server administrator put one or more domains (optionally scoped to specific URL paths) "under attack". While a domain is under attack, every matching HTTP request is first served a lightweight JavaScript splash challenge instead of being passed straight to the site:
- Regular browsers solve the challenge transparently and receive a clearance cookie (its lifetime is configurable per rule); subsequent requests carrying a valid cookie flow through normally.
- Simple bots that cannot run the challenge never reach the application.
UAM is distinct from the per-IP GreyList / Anti-bot Challenge: UAM decisions are keyed on the request's (domain, path) and are configured explicitly, rather than being driven by the state of an IP list.
The server administrator turns the feature on and manages rules for any domain. If the administrator also allows it, site owners can manage rules for their own domains. Rules are managed either from the control panel — see WebShield for the administrator interface and WebShield for the end user one — or with the imunify360-wsctl uam commands described below.
When to use it
Turn UAM on for a specific domain when it is the target of an automated flood (for example scripted checkout or login abuse during a sale) and you want to gate all visitors of that domain behind a challenge, regardless of their IP reputation.
Availability depends on the environment
UAM is not available on every environment WebShield supports. Before relying on it, check whether the current server supports UAM by running imunify360-wsctl filters and confirming the uam filter is listed as available — see WebShield feature availability. Where UAM is unavailable, only the GreyList / Anti-bot Challenge applies.
Compatibility: Supported Setup
cPanel + Apache or Nginx (module loaded) only.
How it works
- A domain is placed under attack by creating a UAM rule. A rule pairs a
domain(optionally narrowed to a path-set) with the clearance-cookie lifetime to grant once a visitor solves the challenge. - When a request matches an active rule, WebShield returns the JS splash challenge and does not forward the request to the backend until the visitor passes.
- UAM is fail-open: if the feature is disabled, the request has no
Host, the rule store cannot be read, or no active rule matches, the request simply proceeds through the normal WebShield flow. UAM never blocks a request outright — it only inserts a challenge. - Whitelisted IP addresses are never challenged: the whitelist is consulted before the application-level checks, so an IP on the White List reaches the site directly. Whitelist any legitimate automation that cannot solve a JavaScript challenge — search-engine crawlers, monitoring, server-side integrations, or
wp-croninvoked over HTTP. - The feature is gated behind a single on/off toggle that is off by default, and all UAM state is stored on the server itself.
Prerequisites
- WebShield version >= 1.45.0 installed and running in an environment where UAM is available (see the note above). The core rule commands and the service toggle have been available since 1.44.2; the per-rule challenge-cookie lifetime and the
uam testcommand described below were added in 1.45.0. - Root access to the server. The
imunify360-wsctl uamcommand described below must be run asroot. Site owners manage their own rules from the control panel instead.
Enabling and disabling UAM
UAM is off by default. Enable the feature before creating rules — while it is disabled, all rule and counter commands fail with a service_disabled error.
imunify360-wsctl uam settings service # show the current {enabled} state
imunify360-wsctl uam settings service enable # turn UAM on, server-wide
imunify360-wsctl uam settings service disable # turn UAM off
Disabling the feature stops all challenges immediately; your rules are preserved and take effect again when you re-enable it.
A second, independent switch controls whether site owners may manage rules for their own domains in the control panel. It is off by default, so UAM starts out administrator-only:
imunify360-wsctl uam settings visibility # show the current {allowed_for_users} state
imunify360-wsctl uam settings visibility enable # let site owners manage their own rules
imunify360-wsctl uam settings visibility disable # administrator-only again
Note
Enable WebShield in Settings does not control UAM. It turns off the GreyList and the Anti-bot Challenge; UAM keeps its own on/off state.
Managing rules
A rule is created from a small JSON payload. The fields are:
| Field | Required | Description |
|---|---|---|
domain | yes | Hostname to put under attack (up to 253 characters). A leading wildcard is accepted: *.example.com matches the subdomains of example.com but not example.com itself, while .example.com matches both. Hostnames are compared verbatim, so write the domain in lower case. |
cookie_ttl | yes | How long a visitor's clearance cookie stays valid after they solve the challenge, before they are challenged again. A Go-style duration string using the units s, m, h (compound values such as 1h30m are allowed), between 10 seconds and 3 days. |
label | no | Free-text note (up to 128 characters). |
paths | no | Path-scoping block (see Path scoping below). Omit it to cover the whole domain. |
A new rule is active as soon as it is created.
# Put a whole domain under attack; re-challenge visitors after 1 hour:
imunify360-wsctl uam add '{"domain":"shop.example.com","cookie_ttl":"1h","label":"Black Friday"}'
# Scope the rule to specific paths (see "Path scoping" below):
imunify360-wsctl uam add '{"domain":"shop.example.com","cookie_ttl":"30m","paths":{"mode":"include","matchers":[{"value":"/checkout","condition":"prefix"}]}}'
List the current rules (a table by default, --json for raw output, --domain and --owner to filter by exact domain or by rule owner):
imunify360-wsctl uam list
imunify360-wsctl uam list --domain shop.example.com --json
imunify360-wsctl uam list --owner alice
The table shows ID OWNER ACTIVE DOMAIN COOKIE_TTL LABEL. The ID is a positive integer assigned by WebShield when the rule is created; you use it to edit or delete the rule. OWNER is admin for rules created by the server administrator, or the user name for a rule a site owner created for their own domain.
imunify360-wsctl uam list
ID OWNER ACTIVE DOMAIN COOKIE_TTL LABEL
7 admin true shop.example.com 1h Black Friday
8 alice true blog.example.com 30m Comment spam
Edit a rule with a partial JSON payload — only active, cookie_ttl, label, and paths can be changed. Temporarily pausing a rule is done by setting active to false:
imunify360-wsctl uam edit 7 '{"active":false}' # pause the rule (keep it for later)
imunify360-wsctl uam edit 7 '{"cookie_ttl":"2h"}' # change the clearance-cookie lifetime
imunify360-wsctl uam edit 7 '{"label":"BF sale"}' # rename
imunify360-wsctl uam edit 7 '{"paths":null}' # clear paths -> back to whole-domain
Delete a rule by ID. Delete is idempotent — deleting an ID that no longer exists still succeeds:
imunify360-wsctl uam delete 7
Path scoping
By default a rule covers the whole domain. Add a paths block to challenge only some URLs. The block has a mode and a list of matchers:
mode: "include"— the matchers list the paths that are under attack. A request is challenged only if it matches one of them.mode: "exclude"— the matchers list exceptions. A matching request is let through; everything else on the domain is challenged.
Each matcher is {"value": "...", "condition": "..."}. A rule may hold between 1 and 32 matchers, and a request matches the block if it satisfies any of them. The available conditions are:
| Condition | Matches when the request URI |
|---|---|
equals | is exactly the value |
prefix | begins with the value |
suffix | ends with the value |
contains | contains the value anywhere |
wildcard | matches the value as a wildcard pattern, where * stands for any number of characters, including / |
query_contains | has a query string containing the value |
query_regex | has a query string matching the value as a regular expression |
The query string is part of what is matched
Matchers are applied to the whole request URI, query string included. An equals matcher for /wp-login.php therefore does not match /wp-login.php?redirect_to=/wp-admin/ — use prefix when the URL may carry a query string. Matching is case-sensitive. Verify the result with uam test.
# Only challenge /api and everything under /checkout:
imunify360-wsctl uam add '{"domain":"shop.example.com","paths":{"mode":"include","matchers":[{"value":"/api","condition":"equals"},{"value":"/checkout","condition":"prefix"}]}}'
# Challenge the whole domain EXCEPT the health-check endpoint:
imunify360-wsctl uam add '{"domain":"shop.example.com","paths":{"mode":"exclude","matchers":[{"value":"/healthz","condition":"equals"}]}}'
Testing which rule matches a URL
uam test checks whether a given URL would be challenged, using the exact same matching as live traffic. It is the quickest way to verify a rule's path scoping without generating real requests.
imunify360-wsctl uam test example.com/path # scheme optional; host required
imunify360-wsctl uam test https://shop.example.com/api?x=1
The scheme is optional, the host is required, and both the path and the query string are significant (only a trailing #fragment is ignored, and an empty path is treated as /). When a rule matches, the command prints that rule as JSON; otherwise it prints No matching rule:
imunify360-wsctl uam test shop.example.com/checkout
[
{
"id": 7,
"owner": "admin",
"active": true,
"label": "Black Friday",
"domain": "shop.example.com",
"cookie_ttl": "1h",
"paths": {
"mode": "include",
"matchers": [
{
"value": "/checkout",
"condition": "prefix"
}
]
}
}
]
Note
uam test only reports a match while UAM is enabled; if the service is disabled it returns a service_disabled error.
Monitoring challenges
Each challenge served for a rule is counted. Use counters to see which rules are actively challenging traffic, busiest first:
imunify360-wsctl uam counters # all rules with hits today, busiest first
imunify360-wsctl uam counters --since 24h # a rolling window instead of "today"
imunify360-wsctl uam counters shop.example.com # filter by exact domain
imunify360-wsctl uam counters 7 # filter by rule id
imunify360-wsctl uam counters --owner alice # filter by rule owner
The single optional argument is auto-detected: a positive integer is treated as a rule ID, anything else as an exact domain. The --since window is one of today (default), 1h, 4h, 24h, 4d, or 7d. Output columns are ID ACTIVE DOMAIN HITS LABEL. Only rules with at least one challenge in the window are listed, and challenge counts are retained for 7 days.
imunify360-wsctl uam counters
ID ACTIVE DOMAIN HITS LABEL
7 true shop.example.com 1523 Black Friday



