WAF-safe encoding
A global security middleware inspects every query string for SQL-injection-shaped substrings — substrings that occur constantly in ordinary URLs and keywords. Encode wrong, and real traffic gets 403'd.
The filter
The backend applies a global WAF middleware (SqlInjectionMiddleware) that lowercases the entire raw query string and returns 403 {"error": "Request blocked due to security policy"} if it contains any of these as a bare substring:
-- ;-- /* */ @@ @ char nchar varchar nvarchar alter begin cast create
cursor declare delete drop end exec execute fetch insert kill open select
sys sysobjects syscolumns table update union waitfor xp_ sp_
' or '1'='1 ' or 1=1 1=1 or 1=1These substrings are everywhere in real content
Look closely:end, open, cast, sys, char, table, @, select, update, union appear constantly inside real URLs and keywords — weekend, broadcast, timetable, /opensource, user@…, /select-plan, /updates. Sending page_url/page_keywords/us_privacy/euconsent_v2 with ordinary URL-encoding will therefore randomly 403 in production — the failure rate tracks exactly how common these substrings are in your traffic's real URLs.The rule
For the four free-text/base64 params (page_url, page_keywords, us_privacy, euconsent_v2), every SDK percent-encodes every byte of the value as %XX (uppercase hex, UTF-8). The raw query then contains only %, hex digits, &, = and the (safe) param names — so no keyword substring can ever survive — while the server still percent-decodes back to the true value for the handler.
Ordinary encoding vs. byte-safe encoding
page_url = "https://example.com/weekend-sale?ref=open"
# Ordinary encodeURIComponent — SURVIVES the substrings "end" and "open":
page_url=https%3A%2F%2Fexample.com%2Fweekend-sale%3Fref%3Dopen
^^^ "end" and "open" still readable -> 403
# Byte-percent-encode every byte instead — no keyword substring can survive:
page_url=%68%74%74%70%73%3A%2F%2F%65%78%61%6D%70%6C%65%2E%63%6F%6D%2F%77%65%65%6B%65%6E%64%2D%73%61%6C%65%3F%72%65%66%3D%6F%70%65%6Eapi_key, slot_id and slot_name use ordinary URL-encoding — their charset (pk_…, UUIDs, publisher-chosen slugs) cannot contain a blocked keyword in practice. Full-encoding them too is harmless, and some SDKs do so defensively.
How this is verified
Every SDK ships a test that reconstructs the exact SQL_KEYWORDS list above and asserts the lowercased raw query it produces for a deliberately nasty page_url contains none of them — including an end-to-end test against a local mock server that reproduces the backend WAF. If you're building a custom client against the raw contract instead of an SDK, port that test first.