Your Filter Says It's Blocking. Here Are Six Tests That Prove It.
A toggle in the on position is not evidence. We audited our own filter in September and found four defects of the same class: visible controls with absent enforcement. Here is the six-test, thirty-minute audit that came out of it — run it against any filter, including ours.

Open your filtering console and look at the category toggles. Count the ones that are on.
Now answer a harder question: for how many of those can you prove, with a browser and a stopwatch, that the thing named on the toggle is actually blocked on a student device right now?
For most schools the honest answer is zero to two. Not because admins are careless — because the console is the only evidence anyone is ever given, and the console is drawn by a different piece of code than the one that decides what loads.
We know this failure shape in unusual detail, because we spent September finding it in our own product. This is the audit we built out of that, written so you can run it against any filter, including ours.
The failure class: a visible control with absent enforcement
A filter can fail in three places, and only one of them is visible.
| Layer | What it does | What you see when it breaks |
|---|---|---|
| The toggle | Records your intent | Nothing. The toggle is on. |
| The mapping | Connects the toggle to a domain list | Nothing. The toggle is on. |
| The enforcement | Decides what loads on the device | A student loads the site |
Every layer above enforcement will report success while enforcement does nothing. The console is not lying on purpose; it simply has no channel back from the proxy that says "I checked, and here is what I did."
Three concrete versions of this, all found in our own code during a September audit of KyberGate:
- Four category toggles were wired to the wrong category. The one labeled Piracy was resolving to a mapping that included mainstream streaming domains. A district that turned on Piracy was quietly blocking Netflix and YouTube. Nothing in the UI said so.
- Two default-on categories shipped with empty domain lists.
self-harmandmalwareboth rendered as armed in the policy builder, and both pointed at an empty static map. They caught content only through asynchronous AI classification, which means a measurable window where the first page is delivered before the block lands. In our own logs: one domain allowed at 22:08:54 and blocked at 22:08:57. Three seconds. One page. - Priority was stored, sorted, displayed, and never compared. Overlapping policies were resolved by merging allow and block lists and then subtracting allows from blocks, so any allow at any priority defeated any block. The ladder in the UI was real. The resolver never consulted it.
We wrote about the third one at length in which filter rule wins. The first two are the reason this post exists: precedence is a design question you can argue about, but an armed toggle over an empty list is just false.
If that can ship in a product whose authors are reading the resolver source every day, assume it can ship in the one you bought.
The audit: six tests, about thirty minutes
Run this on a real student device, signed in as a real student account, on the network students use. Not your admin laptop. Not a guest VLAN. The whole point is to test the thing students experience.
You will need: one managed device, your console open on a second screen, and a clock.
Test 1 — Does each on-toggle block a site you can name?
For every category you have enabled, write down one domain you expect it to block. Then visit all of them on the student device.
This sounds trivial. It is the single highest-yield test in this list, and almost nobody runs it, because it requires the admin to commit to a prediction in writing before checking.
What a pass looks like: a block page, every time, for every category.
What a fail looks like: the page loads. Or — and watch for this one — a different category's block page appears, which means your toggles and your mappings disagree.
The sneaky fail: you cannot think of a domain for a category. If you cannot name what a category contains, you cannot verify it, and neither can the vendor's support team. Ask them to send you five example domains per category. A vendor who cannot produce them on request may not have a list.
Test 2 — Is the block list behind each category non-empty?
Ask your vendor, in writing, for the size of the domain list behind each category you have enabled, and the date it was last updated.
This is the test that catches failure #2 above, and it is not something you can see from the console. An empty list and a 400,000-entry list render identically as a toggle in the on position.
What a pass looks like: a number per category, and a recent update date.
What a fail looks like: "it's AI-powered" as the complete answer. AI classification is genuinely valuable and we use it, but as a supplement. Asynchronous classification means the decision arrives after the request. For a nuisance category, a three-second delay is irrelevant. For self-harm content it is the least acceptable place in the entire product to have a delay, and you deserve to know it exists.
Ask specifically: is this category enforced by a list, by classification, or both? Then ask what the measured delay is for the classification path. If nobody has measured it, that is your answer.
Test 3 — How long does a change take to reach a device?
Block a domain that is currently allowed. Start the clock when you hit save. On the student device, reload that domain every fifteen seconds until it blocks.
Write down the number.
Then repeat the test on a device that has been asleep in a cart for an hour. Wake it and reload.
What a pass looks like: seconds to a minute on an awake, connected device — and a vendor who told you the sleeping-device number in advance rather than after you asked.
What a fail looks like: fifteen to twenty minutes with no explanation. That is the signature of a cache that is populated on read and never invalidated on write. The push path can be perfectly correct and the change still will not land, because something downstream is still serving the old answer from memory.
We hit exactly this. Our notification path was correct — a database trigger fires on commit, a listener picks it up, the policy map is swapped, a websocket message goes out to connected clients. Mainline propagation to a Chromebook is seconds. The lag customers reported came from caches nobody had wired an invalidation into.
The honest promise, and the one we now hold ourselves to, is: five minutes to every reachable device, and the dashboard tells you which devices are not reachable. A sleeping iPad in a charging cart gets nothing until it wakes. No architecture changes that. Any vendor promising instant propagation to every device with no exceptions is describing a device fleet that does not sleep.
Test 4 — Which rule wins when two disagree?
Create two policies that collide deliberately. One blocks a category. One allows a specific domain inside that category. Give them different priorities. Visit the domain.
Then swap the priorities and visit it again.
What a pass looks like: the result changes when you swap the priorities, in the direction the UI implies — and safety-critical blocks do not flip. A category like adult content or self-harm should not be defeatable by a lower-priority allow at all, by anyone, in any org. A CIPA category is a floor, not a setting.
What a fail looks like: the result is identical both times. Your priority ladder is decoration.
Test 5 — Can a safety category be allow-listed by accident?
Open the exceptions or allow-list panel and try to add a domain for your most sensitive category. Self-harm. Adult content. Violence.
What a pass looks like: the product refuses, in the UI and in the API. Ask your vendor to confirm the API refuses too, because a UI-only guard is bypassed by any integration, script, or bulk import.
What a fail looks like: it accepts the entry. We found our own exceptions panel would accept allow-list entries for self-harm and adult content, with no guard anywhere. The fix was to hard-remove those categories from exceptions in both the UI and the API, while leaving genuinely debatable categories — health curriculum needs drugs and alcohol content sometimes — still exceptable.
Note what this test really measures: whether anyone has decided which categories are non-negotiable. A product where everything is configurable has made that decision by default, in the wrong direction.
Test 6 — Does the app path get filtered, or only the browser?
On an iPad or a Chromebook with Android apps, open a social or video app rather than a browser tab. Try content you blocked in Test 1.
What a pass looks like: blocked in the app too, because filtering happens at the network layer rather than inside the browser.
What a fail looks like: blocked in Chrome, fine in the app. Browser-extension filtering cannot see traffic that never enters the browser, and students work this out faster than procurement does.
This is the test we care most about on iPads, because it is where the category is weakest across the board — VPN-based approaches that drain the battery, configuration profiles that silently stop applying, and no inspection of encrypted traffic. KyberGate filters iPads through a cloud proxy with real SSL inspection, which is a different architecture, not a better version of the same one.
What to do with your results
Keep the written record. Six tests, pass or fail, with dates. It is worth more than any vendor datasheet for three separate conversations:
- Renewal. "We ran these six tests and three failed" is a negotiating position. "We feel the filter is unreliable" is not.
- Your board or superintendent. A table of verified controls is the artifact that answers "are we actually protecting students" without a technical digression.
- CIPA. Certifying compliance is a statement about enforcement, not about configuration. A toggle you have never tested is not evidence of anything.
Re-run the audit after every vendor update that touches categories or policy, and at the start of every school year. Configuration drifts, lists change hands, and a feature can regress without any UI change at all — which is precisely why the console cannot be your evidence.
Why we published our own failures
Writing this up meant listing four defects we shipped. That is an odd marketing decision, and it is deliberate.
Every filter in this category has some version of these bugs, because the structural cause is the same everywhere: the layer that renders your intent and the layer that enforces it are different code, and nothing automatically keeps them honest. The only question is whether anyone is looking. We found ours by auditing our own resolver against our own UI, then filing every gap as a tracked issue before writing a line of fix code.
What we would not accept from a vendor, and what you should not accept from us, is a console that reports confidence it has not earned. So the standard we hold now is narrow and testable: a toggle that is on blocks the thing named on the toggle, the rule that wins is explainable in one sentence, and where a change cannot reach a device, the dashboard says so.
Run the six tests. If we fail one, we want the report.
Want to see the six tests run on your actual network?
Start a free 30-day pilot and we will run the audit with you, on your devices, and hand you the written results — including anything that fails.
See pricing — per-device, transparent, no hidden fees.
Frequently Asked Questions
+
+
+
+
+
+
Ready to protect your students?
Deploy KyberGate in under 30 minutes. No hardware required.
Request a Demo