Skip to main content

Invalid user agent and Unknown user agent

These two WAAP policies work together to identify and block requests that lack a standard user-agent parameter. If the agent is missing, this can indicate that an illegitimate client is being used.

Most browsers provide user agent information across the network to validate a client's authenticity and purpose. User agent strings typically follow this syntax:

User-Agent: <product> / <product-version> <comment>

Where:

  • <product>: A product identifier — its name or development codename.
  • <product-version>: Version number of the product.
  • <comment>: Comments containing additional details — sub-product information.

Both policies are part of the Anti-automation and bot protection group and are enabled by default. To change the state of a policy, navigate to the CDB Technical Web Portal:

  1. Navigate to WAAP > Bot Management.
  2. In the domain dropdown at the top right of the page, select the domain.
  3. Open the Bot Attacks tab.
  4. Find the Invalid user agent or Unknown user agent policy and click the dropdown next to it to enable or disable it.

The Policies endpoints manage the Invalid user agent and Unknown user agent rules. Both policies are enabled by default and belong to the Anti-automation and bot protection ruleset. Response examples include only the fields used in each step.

An API token is required, along with the ID of a WAAP-protected domain and the Python or Go SDK installed for SDK examples.

export GCORE_API_KEY="{YOUR_API_KEY}"
export WAAP_DOMAIN_ID="{YOUR_DOMAIN_ID}"

View policy states

Retrieve the current state of the Invalid user agent and Unknown user agent policies for a domain.

import gcore
import os

client = gcore.CDB(api_key=os.environ["GCORE_API_KEY"])
domain_id = int(os.environ["WAAP_DOMAIN_ID"])

TARGET_IDS = {"S3008869", "S3008870"}

rule_sets = client.waap.domains.list_rule_sets(domain_id)
aa_set = next(
    rs for rs in rule_sets if rs.resource_slug == "anti-automation-bot-protection"
)

for policy in aa_set.rules:
    if policy.id in TARGET_IDS:
        status = "enabled" if policy.mode else "disabled"
        print(f"{policy.name}: &#123;status&#125; ({policy.id})")
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/option"
)

func main() {
    client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
    domainID, _ := strconv.ParseInt(os.Getenv("WAAP_DOMAIN_ID"), 10, 64)

    targetIDs := map[string]bool{"S3008869": true, "S3008870": true}

    ruleSets, _ := client.Waap.Domains.ListRuleSets(context.Background(), domainID)
    for _, rs := range *ruleSets {
        if rs.ResourceSlug == "anti-automation-bot-protection" {
            for _, policy := range rs.Rules {
                if targetIDs[policy.ID] {
                    status := "disabled"
                    if policy.Mode {
                        status = "enabled"
                    }
                    fmt.Printf("%s: %s (%s)\n", policy.Name, status, policy.ID)
                }
            }
        }
    }
}
curl -X GET "https://api.cdb-staging.cdn.orange.com/waap/v1/domains/${WAAP_DOMAIN_ID}/rule-sets" \
  -H "Authorization: APIKey ${GCORE_API_KEY}" \
  | jq '[.[] | select(.resource_slug == "anti-automation-bot-protection") | .rules[] | select(.id == "S3008869" or .id == "S3008870") | {name, id, mode}]'

The response lists both policies with their current state. mode: true means enabled; mode: false means disabled:

[
  {
    "name": "Invalid user agent",
    "id": "S3008869",
    "mode": false
    // ...
  }
  // ...
]

Toggle a policy

Switch a policy between enabled and disabled. Each call flips the current state. Use the policy ID from the View policy states response or from the table below.

This endpoint toggles the current state rather than setting a specific value. If the target state is unknown, retrieve the current policy state first using the View policy states request above.

import gcore
import os

client = gcore.CDB(api_key=os.environ["GCORE_API_KEY"])
domain_id = int(os.environ["WAAP_DOMAIN_ID"])

# S3008869 = Invalid user agent, S3008870 = Unknown user agent
policy_id = "S3008869"

result = client.waap.domains.policies.toggle(policy_id, domain_id=domain_id)
status = "enabled" if result.mode else "disabled"
print(f"Invalid user agent is now &#123;status&#125;")
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/option"
    "github.com/G-Core/gcore-go/waap"
)

func main() {
    client := gcore.NewClient(option.WithAPIKey(os.Getenv("GCORE_API_KEY")))
    domainID, _ := strconv.ParseInt(os.Getenv("WAAP_DOMAIN_ID"), 10, 64)

    // S3008869 = Invalid user agent, S3008870 = Unknown user agent
    policyID := "S3008869"

    result, _ := client.Waap.Domains.Policies.Toggle(context.Background(), policyID, waap.DomainPolicyToggleParams{DomainID: domainID})
    status := "disabled"
    if result.Mode {
        status = "enabled"
    }
    fmt.Printf("Invalid user agent is now %s\n", status)
}
# Set POLICY_ID to S3008869 (Invalid user agent) or S3008870 (Unknown user agent)
export POLICY_ID="{POLICY_ID}"

curl -X PATCH "https://api.cdb-staging.cdn.orange.com/waap/v1/domains/${WAAP_DOMAIN_ID}/policies/${POLICY_ID}/toggle" \
  -H "Authorization: APIKey ${GCORE_API_KEY}"

The API returns the updated policy state. mode: true confirms enabled; mode: false confirms disabled:

{"mode": true}

Policy reference

PolicyDescriptionActionDefault
Invalid user agentBlocks requests from user agents known to be associated with malicious activity.BlockEnabled
Unknown user agentApplies a transparent JavaScript-based browser check to requests from unrecognized user agents.HandshakeEnabled

Both policies belong to the Anti-automation and bot protection ruleset, which includes six additional policies for managing automated and bot traffic.