Stack shields

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

On this page

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 to switch the shield off on a path.

Shields follow the site's mode: they block in active, only record in log and don't run in off (or with waf_level=off).

IdShieldBlocksAnswer
1001WordPress hardeningOnly on sites with stack=wordpress.404
1002SSRF (query)Query parameters that carry a URL to an internal address.403
1003Open redirectQuery parameters that redirect to another site.403
1004PaginationOne IP walking through many consecutive pages.429
1005Source mapsRequests for .map files.404
1006GraphQLIntrospection and very deep queries.404
1007Prompt injectionJailbreak phrases sent to AI endpoint paths.403
1008SSRF (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): 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.

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).

Last updated:

↑↓ to navigate↵ to openesc to close