---
title: "Set a cluster-wide baseline for Gateway WAF"
description: "Set the cluster-wide WAF baseline every namespace inherits — action mode, Core Rule Set state, and paranoia level."
product: "Calico Cloud"
version: "v24.0.0"
section: "Threat defense"
canonical_url: "https://docs.tigera.io/calico-cloud/threat/gateway-waf/set-a-baseline"
---

# Set a cluster-wide baseline for Gateway WAF

> **SECONDARY:** This feature is tech preview. Tech preview features may be subject to significant changes before they become GA.

The baseline is the cluster-wide default every namespace inherits — action mode, Core Rule Set, and paranoia level. Set it once so every Gateway starts protected and teams tune from a known-safe starting point.

## Prerequisites

- Gateway WAF is enabled. See [Enable Gateway WAF](https://docs.tigera.io/calico-cloud/threat/gateway-waf/enable.md).
- Cluster-admin rights — `GlobalWAFPolicy` is cluster-scoped.

## Set the baseline

1. Create the singleton `GlobalWAFPolicy`. It must be named `default` — other names are rejected by the admission webhook. Start in `Detect` mode: it logs matches without blocking, so you can measure false positives before switching to `Block`:

   ```yaml
   apiVersion: applicationlayer.projectcalico.org/v3
   kind: GlobalWAFPolicy
   metadata:
     name: default
   spec:
     defaultAction: Detect        # start here; promote to Block after validating false-positive rate
     coreRuleSet:
       state: Enabled
       paranoiaLevel: 1
   ```

   Apply it with `kubectl apply -f globalwafpolicy.yaml`.

2. Pick a paranoia level. Higher catches more attacks at the cost of more false positives:

   | Level | Posture                                    | Typical use                                             |
   | ----- | ------------------------------------------ | ------------------------------------------------------- |
   | 1     | Balanced — low false-positive rate         | General-purpose default; a safe starting point          |
   | 2     | Moderate — catches common evasion patterns | APIs that handle sensitive data                         |
   | 3     | Strict — flags most suspicious patterns    | High-value or compliance-regulated endpoints            |
   | 4     | Paranoid — near-zero tolerance             | Extremely high-security targets; expect false positives |

   > **SUCCESS:** Start at level 1 cluster-wide; let application operators raise it per namespace, and enforce a minimum later via a validation policy.

3. Once you've validated the false-positive rate, set `defaultAction: Block`. Calico Cloud then returns HTTP 403 for matching requests.

## Add organization-wide rules with a GlobalWAFPlugin (optional)

A `GlobalWAFPlugin` holds custom ModSecurity rules applied cluster-wide via the global policy's `plugins[]` list — for a security baseline every namespace inherits.

1. Create the `GlobalWAFPlugin`. Rules use the four lifecycle slots described in [Write custom rules](https://docs.tigera.io/calico-cloud/threat/gateway-waf/write-custom-rules.md):

   ```yaml
   apiVersion: applicationlayer.projectcalico.org/v3
   kind: GlobalWAFPlugin
   metadata:
     name: org-baseline
   spec:
     description: "Organization-wide security baseline rules"
     config: |
       SecAction "id:800001,phase:1,pass,nolog,setvar:tx.enforce_https=1"
     before: |
       SecRule REQUEST_HEADERS:X-Forwarded-Proto "!@streq https" \
         "id:800002,phase:1,deny,status:403,msg:'HTTPS required',chain"
       SecRule TX:ENFORCE_HTTPS "@eq 1" ""
     rules: |
       SecRule REQUEST_HEADERS:X-Request-ID "@rx ^$" \
         "id:800003,phase:1,deny,status:400,msg:'Missing X-Request-ID header'"
     after: |
       # Cluster operator's after slot runs last in the merge order.
       SecRule TX:BLOCKING_ANOMALY_SCORE "@gt 0" \
         "id:800099,phase:5,pass,log,msg:'Request blocked by WAF'"
   ```

2. Reference it from `GlobalWAFPolicy.spec.plugins[]` — for example `plugins: [{kind: GlobalWAFPlugin, name: org-baseline}]`. `plugins[]` is ordered by array position, up to 64 entries; `WAFPlugin` entries can be added here too.

## Verify the baseline

1. Confirm the policy is accepted:

   ```bash
   kubectl get globalwafpolicy default
   ```

   ```text
   NAME      ACCEPTED   AGE
   default   True       30s
   ```

Detail lives in `.status.conditions` (`kubectl get globalwafpolicy default -o yaml`): `Accepted=True` reason `Accepted` = programmed; `Accepted=False` reason `ValidationFailed` = a validation policy blocked it (the message describes the violation). See [Status conditions](https://docs.tigera.io/calico-cloud/threat/gateway-waf/reference.md#status-conditions).

Every namespace with a `WAFPolicy` inherits `defaultAction`, `coreRuleSet.state`, and `coreRuleSet.paranoiaLevel` from `GlobalWAFPolicy` unless it overrides them:

```text
GlobalWAFPolicy (baseline)
  └─ WAFPolicy in namespace payments  → overrides action: Block, paranoiaLevel: 2
  └─ WAFPolicy in namespace team-a    → inherits everything from GlobalWAFPolicy
```

## Next steps

- [Attach WAF to a Gateway or route](https://docs.tigera.io/calico-cloud/threat/gateway-waf/attach-waf-to-a-route.md) — turn on inspection for a target.
- [Write custom rules with plugins](https://docs.tigera.io/calico-cloud/threat/gateway-waf/write-custom-rules.md) — add app-specific detections and exceptions.
- [Validate configuration with Rego](https://docs.tigera.io/calico-cloud/threat/gateway-waf/validate-config.md) — enforce compliance guardrails on the merged config.
