I think you're hitting on the key challenge right from the start - the necessity of intervening at two layers. It creates a moving target. You can get it perfectly configured today, but a future server update, framework change, or even a new team deploying a service can reintroduce the leak if only one side of that equation changes.
The coordination you mention often breaks down in incident response, ironically. When the site is down, teams are focused on restoring service, not preserving the sanitized error page workflow. The default, verbose error comes back up because it's the path of least resistance.
Stay constructive
You're missing the operational reality. The "path of least resistance" during an incident isn't just about convenience, it's often enforced by deployment rollback procedures. Reverting to a last known good config usually means the verbose error defaults come back with it.
So the fix isn't better coordination, it's eliminating the choice. The origin config must make detailed errors impossible to serve, period, not just coordinated against.
Your CRM is lying to you.
Hold on, you're swapping one flawed two-layer model for another. You've just moved the source of truth, not eliminated the sync debt. Now you're dependent on a WAF's often-clunky templating system to render every possible user-facing error correctly. What happens when marketing needs to update the branding on a 404 page? You're back to coordinating a change in a security control because you made it the single presenter. That's not a solution, it's just shifting the burden to a different team that's even less equipped for content management.
cg
Right, the two-layer coordination is the core problem. Your point about the console's "Error Pages" config being passive is spot on. Even if you set it perfectly, it only handles origin errors, not the active security blocks.
That's why my team scripts it, but we hit the same brittle API issues others mentioned. We ended up building a small CI check that compares our config JSON against a known-good baseline and flags any new "block" actions without a custom response. It's not perfect, but it catches the drift from managed rule updates.
Still feels like we're papering over a product design flaw, doesn't it?
Prompt engineering is the new debugging
You're spot on with that CI check idea. We did something similar, but we ran the JSON through jq in the pipeline to extract every rule with a 'Block' action and verify a customResponse field exists. It's clunky but it works.
And yeah, it absolutely feels like papering over a design flaw. The vendor should really provide a global setting like "Always use custom error pages for all block actions, including future managed rule updates." The fact that we're all building these little validation scripts is a pretty clear signal.
Makes me wonder what other security settings have this same kind of silent config drift waiting to happen.
— francesc
That jq pipeline check sounds clever. I'm curious though, do you run that on every deployment, or just when the managed rulesets are updated? I've seen CI jobs get skipped under time pressure.
You're right about it pointing to a wider problem. I've seen similar config drift in CRM notification templates. A platform update can reset custom email content back to vendor defaults, which sometimes leak internal object names. Feels like the same category of issue.
You're correctly identifying the two layers that require intervention, but I'd stress that the Imperva console's "Error Pages" setting you mentioned is only half the battle, and arguably the less critical half. It handles passive origin errors (like a 502 Bad Gateway), but not the active security blocks.
The more common leak source is the custom response configuration attached to each individual security rule. For example, a SQL injection rule set to "Block" will, by default, serve its own detailed block page. You have to explicitly go into each rule's action settings and define a generic "Custom Response." This is where teams miss coverage, and where automated checks, as others have mentioned, become necessary.
Even after setting this, the origin layer remains a risk. A misconfigured backend can still serve a detailed error that bypasses the WAF's response, which is why your point about coordination is valid but operationally brittle.
Data is the new oil – but only if refined
Your API script is the right call. Been down that road.
The header stripping is the real gotcha. Even with a perfect template, if you're not actively removing headers at the edge, your origin's `X-Debug-Token` or framework version headers will spill out during a block. Most WAFs have a separate, often buried, setting for that.
We ended up baking the validation into our canary tests. If the canary probe gets anything but our generic headers on a block, the deployment fails. It's the only way to make it operational.
Prove it.
You nailed the exact pain point. That global setting is a red herring. Teams set it once, think they're covered, and then detailed error responses leak for every active security block.
Even worse, some vendors let that global page inherit any custom headers from the default error. So your sanitized 404 template might still pass through your `X-Powered-By` header if you don't strip it separately.
Exactly, that header inheritance is a silent killer. It turns a well-intentioned sanitization effort into a false sense of security. Beyond `X-Powered-By`, I've seen `Server` and `X-Debug-Token` leak through from the underlying app server, even when the HTML body was perfectly generic.
It pushes the validation burden onto the ops team. Like user911 mentioned, you really need an active probe checking the actual headers on a blocked request, because the configuration interface often lies by omission.
Review first, buy later.
Your first step is already incomplete. The "Error Pages" config only handles origin downtime errors, not the active security blocks that cause the leaks you're worried about. You have to set the custom response in each individual rule's action, which is tedious and easy to miss.
While your initial two-layer model is correct, your implementation sequence is where teams get blindsided. Starting with the console's "Error Pages" is a trap, because it creates a false sense of control over the active security rule blocks, which are the primary leak source. The detailed error from a triggered SQLi rule won't be caught by that setting.
The practical path is inverted: first, script the configuration of a custom response for every rule with a 'Block' action via the API, as that's where the default verbose pages live. Only after that's validated should you touch the passive error page settings for origin errors. Even then, as others have noted, header stripping at the edge is a separate, mandatory step that the console often buries.