# Stack shields

> Eight targeted protections that run after the WAF rules, for WordPress, SSRF, open redirects, pagination, source maps, GraphQL and prompt injection.

Shields are small, specific checks that the edge runs after OWASP CRS and OpenWAF's rules. Each one has a pseudo rule id between 1001 and 1008: that id appears in the security events and is the `rule_id` you use in a [WAF exception](https://developers.openwaf.dev/waf/waf-exceptions/#rule-id) to switch the shield off on a path.

Shields follow the site's [mode](https://developers.openwaf.dev/waf/modes-and-levels/#modes): they block in `active`, only record in `log` and don't run in `off` (or with `waf_level=off`).

| Id | Shield | Blocks | Answer |
|---|---|---|---|
| 1001 | WordPress hardening | Only on sites with `stack=wordpress`. | 404 |
| 1002 | SSRF (query) | Query parameters that carry a URL to an internal address. | 403 |
| 1003 | Open redirect | Query parameters that redirect to another site. | 403 |
| 1004 | Pagination | One IP walking through many consecutive pages. | 429 |
| 1005 | Source maps | Requests for `.map` files. | 404 |
| 1006 | GraphQL | Introspection and very deep queries. | 404 |
| 1007 | Prompt injection | Jailbreak phrases sent to AI endpoint paths. | 403 |
| 1008 | SSRF (JSON body) | URLs to internal addresses inside JSON bodies. | 403 |

A `rule_id` 0 exception (every WAF rule) does **not** switch shields off: use the shield's own id.

## WordPress hardening

On sites with `stack=wordpress`, answers 404 to `/xmlrpc.php`, `/wp-json/wp/v2/users` without an `Authorization` header (user enumeration), `/wp-includes/version.php` and `/readme.html` (version disclosure), and any path containing `wp-config`.

## SSRF

Checks the values of query parameters named `url`, `webhook_url`, `callback_url`, `target_url`, `redirect_url`, `return_url`, `dest`, `destination`, `uri`, `endpoint`, `proxy`, `fetch`, `src`, `href`, `link`, `next` or `continue` (1002), and every string that looks like an absolute URL inside a JSON body (1008). It blocks:

- the schemes `file`, `gopher`, `dict`, `ldap`, `jar` and `netdoc`;
- the host names `localhost`, `metadata`, `metadata.google.internal`, `metadata.azure.com` and any name ending in `.localhost` or `.internal`;
- loopback, private, link-local, unspecified and carrier-grade NAT (`100.64.0.0/10`) addresses, also written in hexadecimal, octal or decimal forms such as `0x7f.1` or `2130706433`.

Relative paths and free text are never blocked.

## Open redirect

Checks query parameters named `redirect`, `redirect_url`, `redirect_uri`, `return`, `return_url`, `returnto`, `return_to`, `next`, `dest`, `destination`, `rurl`, `continue`, `callback`, `callback_url`, `forward`, `goto`, `success_url`, `cancel_url`, `checkout_url` or `payment_url`. An absolute or protocol-relative URL (`//evil.example`, `https:\\evil.example`) passes only when it points to:

- the same registrable domain as the site (`api.example.com` may redirect to `example.com`);
- a host in the site's `redirect_allow_hosts` ([settings](https://developers.openwaf.dev/waf/settings/#redirect-allow-hosts)): an entry matches itself and its subdomains;
- a payment provider every site may use, such as `stripe.com`.

## Pagination

Blocks one IP that requests 40 consecutive pages of the same path within 5 minutes (`?page=` or `?offset=` with `limit`, `take`, `size`, `per_page`, `pageSize`, `page_size` or `perPage`). Infinite scroll by a person stays well below it.

## Source maps

Answers 404 to any path ending in `.map`, so source maps that expose your source code are never served.

## GraphQL

For paths ending in `/graphql`: blocks introspection (`__schema`, `__type`…) and queries nested more than 10 levels deep.

## Prompt injection

For paths containing `/ai/`, `/search-ai/`, `/chat/`, `/assistant/`, `/copilot/`, `/api/ai/`, `/api/chat/` or `/api/assistant/`: blocks request bodies with known English jailbreak phrasings, such as "ignore previous instructions", system prompt extraction or "developer mode". For a full policy on your own AI endpoints (detectors in English and Spanish, body caps, per-IP and per-session limits), use [AI endpoint protection](https://developers.openwaf.dev/ai-crawl-control/ai-endpoints/).

## Body inspection

The body shields (GraphQL, prompt injection, SSRF in JSON) read up to 1 MiB of a JSON, GraphQL or AI endpoint body and always forward the whole body. Multipart uploads are not inspected by them. A body larger than that limit is refused with 413, unless the path has a WAF exception for rule 10101 (see [Troubleshooting](https://developers.openwaf.dev/waf/troubleshooting/#large-bodies)).
