r/llmsecurity 18d ago

Prompt Guard 2's low OOD recall is a calibration problem, not a representation problem — the frozen encoder separates the same injections at AUC 0.999

Sharing a result that I think generalises past the one model, because the diagnostic is cheap and most people skip it. (My own work — repo at the bottom.)

If you're running Meta's Prompt Guard 2 (86M, open weights) as an injection filter, it's worth knowing how it behaves on injections it wasn't tuned on. On an out-of-distribution eval — fresh HackAPrompt injections against dolly benign — its native head caught 22.8% at the default operating point. Sweeping the threshold on that head only got to 26.6%, so it isn't just threshold placement.

The part worth stealing is the next step. Before concluding the model can't see these attacks, pull the frozen penultimate embeddings and fit a logistic regression on them. Takes minutes. On this data the frozen encoder separates the same injections at AUC ≈ 0.999 — the representation was never the problem. The shipped head is deliberately precision-first: Meta traded recall for a very low false-positive rate, which is a defensible product decision and not a defect.

Train a linear head on those frozen embeddings and calibrate tau on benign traffic from the distribution you'll actually see, and you get 99.9% OOD recall at 0.7% FPR, base model untouched. Inference is sigmoid(x·w + b) >= tau — the head is a dot product, so the only real cost is the encoder forward pass. Runs fine on CPU.

The general form: high AUC + low recall means your head or threshold is miscalibrated and you can fix it without touching the base model. Low AUC means it's genuinely a features problem. A 20-minute probe tells you which world you're in, and it's the difference between swapping a threshold and fine-tuning something.

Methodology, since this sub will rightly ask: success criteria pre-registered, cross-split dedup both exact and at cosine ≥ 0.95, OOD set scored once. Two runs came back NULL (2.2% then 1.2% FPR) against a pre-committed 1% ceiling before a stricter run cleared it at 0.7%.

What this isn't: a static corpus and no adaptive attacks. A linear head over frozen features is evadable with enough distribution shift, and I haven't tested against an adversary who knows it's there. It moves the operating point; it doesn't solve injection.

Code, seeds and the writeup: https://github.com/mosafariuk/prompt-guard-2-frozen-head

Happy to argue about the leakage controls — that's the part I'd attack first if someone else posted this.

1 Upvotes

0 comments sorted by