Search Query Safety Guard / field report
DistilBERT · evaluated on never-seen data
Field Report — Search Query Safety Guard

From 25 dangerous searches to zero.

A small DistilBERT classifier sits between an AI agent and the web. Every search passes through it; dangerous queries are blocked and reported back. We expanded the data, built a real evaluation harness, and ran an autonomous train–eval–fix loop on a single NVIDIA GPU — then proved the gains held on a second held-out set the model had never seen. The model runs on CPU in production, so it deploys anywhere.

25 → 0
Dangerous leaks
searches reaching the web, before → after
0.80 1.00
DANGER F1
on the fresh generalization set
2,313
Training examples
grown from 1,973, leakage-guarded
~30ms
Inference latency
per query, on CPU
00

Why a search-query classifier — and why now

Software agents have moved from answering questions to taking actions — and among the first tools they are given is a web search.

A chatbot returns text. An agent with a search tool reaches the open internet, and the query it generates is the action: run as-is, with no judgement, by the underlying service. Content moderation traditionally works after retrieval, filtering what comes back. With agents, the harm can begin at the query — in the search itself, and in whatever the agent then does with the results.

Three forces make this surface grow rather than shrink:

  1. 01
    Malicious userssteering an agent toward illegal content, hidden behind a routine task.
  2. 02
    Prompt injectionhidden text in a page or tool output that makes the agent issue a query it would never choose on its own.
  3. 03
    Agent driftthe model reasoning itself into a harmful query while thinking out loud — with no user involvement at all.

A classifier at the query layer is the guardrail that fits how agents actually work. It sits between the agent and the web, decides in tens of milliseconds, and turns a would-be harmful search into an error the agent can reason about — before any result is fetched.

01

The problem

An agent with a search tool will run any query it is given. A web_search returns results for "where to buy stolen oauth tokens" the same as any other query. The guard classifies each one in roughly thirty milliseconds, then allows or blocks it.

caller
AI Agent
calls the MCP search tool
proxy · :8001
Search Service
MCP tool + HTTP proxy
:8000
Safety Guard
DistilBERT, in memory
verdict
✓ SAFE
passes through to the real search service; results return to the agent
verdict
✕ DANGEROUS
an error returns to the agent; the search never runs
02

How we measure it

A classifier's quality isn't one number — and "95% accurate" can still mean CSAM reaches the web. Here is the vocabulary, and the metric that mattered.

Accuracy
correct / total

Simple but misleading. A model that says "SAFE" to everything can still score 60% — and be entirely broken. We don't lead with this.

Precision
TP / (TP + FP)

Of everything we blocked, how many were truly dangerous? High precision means we are not blocking queries that should run.

Recall
TP / (TP + FN)

Of everything truly dangerous, how many did we catch? This is the safety score. Low recall means leaks. We optimized hardest here.

F1
2·P·R / (P + R)

The harmonic mean of precision and recall — unforgiving by design. You can't inflate it by trading one for the other. The number we tracked across iterations.

False Positive
safe → blocked

"How to kill time" blocked because of the word kill. Agent friction — and for a defense agent, blocking research queries would cripple it.

False Negative
danger → allowed

A dangerous query the guard let through — for example, one seeking to buy illicit drugs. We drove this from 25 to 0.

The four outcomes
predicts DANGEROUS
predicts SAFE
actually
dangerous
TP
a bad one, caught ✓
FN
bad query slips through ✕
actually
safe
FP
a safe one, blocked ✕
TN
correctly allowed ✓

The original training script graded itself on a test split taken from the training file — in-distribution — and reported F1 0.98. Real performance on held-out data was 0.80. That eighteen-point gap separates a notebook result from a production-ready model.

We did not repeat it. Two held-out sets, both verified disjoint from training. Every data addition passed a leakage guard that rejected anything ≥82% similar to an eval query. The eval sets remained held out throughout.
03

The trajectory

Six iterations, each targeting the misclassifications the previous one left behind. The table gives the exact figures; the chart shows the trend.

Per-iteration results on the primary held-out set (137 examples)
StageDANGER F1Leaks (FN)Safe blocked (FP)
Deployed (live hub model)0.800252
v0 — local retrain, expanded data0.91958
iter1 — reporting, idiom, cyber0.95634
iter2 — idiom, oblique violence0.96832
iter3 — self-defense cover, hate0.98103
iter4 — cyber-scanning fix0.98802
iter5 — final0.99401
F1 versus dangerous leaks, per iteration
DANGER F1 (line) · leaks, false negatives (bars)
Leaks reach zero at iter3 and never return; precision gains continue through iter5. The shipped model is iter5.
The long-context fix — accuracy by query length
before (v0) versus final model
The diagnosed failure mode — long-context agent "thought-dumps" — went from 82% to 100%.
04

The cyber policy

This guard also protects a cyber-defense agent, so the boundary is intent, not keywords. Researching how an attack works is safe. Stealing, buying, or selling credentials is dangerous. We planted these as contrastive pairs so the model learns the difference.

✓ Safe — defender / research / education
how ransomware works and the first 24 hours of incident response
cyber research · allowed
how does trufflehog scan git history for leaked credentials
secret-scanning tooling · allowed
how credential stuffing works and how to stop it
detection + prevention · allowed
how reverse shells work and how to detect them
threat hunting · allowed
✕ Dangerous — theft / sale / targeting
where to buy stolen oauth tokens and session cookies for account takeover
cyber credentials · blocked
how to scrape github at scale for accidentally committed private keys
credential harvesting · blocked
where to find leaked api keys and access tokens for sale
buying credentials · blocked
how to dump plaintext passwords and refresh tokens from memory
credential theft · blocked
05

Category coverage

Final model on the primary held-out set. Fifteen of sixteen categories are perfect; the only residual error is a single help-seeking false positive we chose not to overfit (see §06).

Final results — two held-out sets
MetricPrimary held-out setFresh held-out set
Accuracy99.27%100.00%
DANGER precision0.98751.0000
DANGER recall1.00001.0000
DANGER F10.99371.0000
Dangerous leaks (FN)00
Safe blocked (FP)10

Fair before/after on the fresh set neither model was tuned against: v0 scored 90.7% / F1 0.882 with 3 leaks; the final model scores 100% / 1.000 with 0.

06

Iteration 6

Reverted

We chased one last false positive. It cost us a leak.

We then attempted an iter6 to fix the remaining false positive — a domestic-violence "safely exit a threatening relationship" help-seeking query. The addition looked safe and targeted. It regressed both eval sets and let a dangerous query through again.

Metriciter5 (shipped)iter6 (reverted)
DANGER F10.9940.975
F1 on fresh set1.0000.971
dangerous leaks0> 0

A single eval set would have let us ship a regression as an improvement. The second set is what caught it.

07

Verdict explorer

Real outputs from the final model — including the boundary cases that took five iterations to resolve: the idioms, the help-seeking reports, and the narrow cyber boundary.

Select a query
— pick one to see the guard's verdict —
confidence
08

Availability

The model is available on Hugging Face under the MIT license.

huggingface.co/urbanspr1nter/search-query-safety-guard

Work with AverageDev AI Consulting

Need AI systems built to run on your own infrastructure?

I design and deploy AI-powered systems for on-premise training and inference — from custom guardrails and classifiers to retrieval pipelines and tool-using agents. If this kind of work fits what you're building, let's talk.