Article · 14 September 2026 · 4 min read

Tuning a WAF without turning it off

The web apps started failing with 403s that nobody could reproduce from a terminal. The culprit was not a bug. It was the firewall doing exactly what it was told: reading an innocent filter string as a SQL injection attack.

The crime scene

We put an API Gateway in front of a set of web apps: one authenticated entry point, OpenAPI specs generated by a script instead of maintained by hand, and Cloud Armor with the OWASP Core Rule Set in front of everything. Sensible defaults, and then this: the UIs speak RSQL, so a routine request carries something like filter=year==2026 and month==8. To the SQL-injection rule, doubled equals signs and a lowercase and are what chained injection looks like. Block.

A false positive from your WAF does not look like a firewall decision. It looks like your API being broken.

The wrong fixes

The tempting moves are all bad. Turning the SQLi rules off entirely trades a nuisance for an open door. Encoding the filter syntax differently pushes the cost onto every client. And exempting whole paths from inspection quietly grows into a firewall that inspects nothing anyone uses.

The fix that held

Cloud Armor's preconfigured rules have two useful dials: a sensitivity level per rule group, and opt-outs for individual rule IDs. We tuned the SQLi group down to the level that stops reading RSQL as an attack, opted out the two specific rule IDs that misfired, and left the rest of the OWASP set enforcing. Then we made those two dials module inputs in the Terraform, so the next service with a query grammar gets a documented knob instead of a copy-pasted exception.

What we wrote down on the way

Perimeter work has a way of surfacing what everyone assumed someone else had checked. Ours surfaced three: one environment validating legacy tokens against another environment's key set, a security policy attached to zero backend services, and an internal ingress reachable without authentication. None of them was the job we came for. All of them went into the report, because a gap you write down gets fixed, and a gap you assume stays a gap.

A perimeter someone actually owns

Gateways, WAF rules, and the gaps nobody wrote down: this is ordinary retainer work for us. If your firewall is eating requests or your perimeter is held together by assumptions, tell us.

Get in touch