Tuning false positives

A rule is firing on legitimate work. Your options are narrower than you might expect, so it is worth being clear about what is actually available.

Warning

There is no allowlist. You cannot exempt a phrase, a user, a repository, a model, or a client from a guardrail. There is no exception list, no bypass token, and no per-user policy.

A rule that is enabled applies to every request your organisation makes. The three mechanisms below are the whole toolkit.

1. Narrow the pattern

This is the right answer roughly nine times out of ten. Most false positives are a pattern that was written to be safe and ended up being broad.

Anchor on structure. The single most common mistake is matching on length alone:

[0-9]{9}          ✗ matches timestamps, port ranges, row counts, half your traffic
\bEMP-[0-9]{6}\b  ✓ matches an employee ID

Require the part that makes it dangerous. A connection string is only a leak if it carries a credential:

(?i)postgres://\S+                      ✗ fires on postgres://localhost/dev
(?i)postgres://[^\s]+:[^\s]+@           ✓ fires only when there is a user:password@

Use word boundaries. Without \b, an identifier pattern matches inside longer tokens and cuts them in half when it redacts.

Constrain with alternation instead of exclusion. RE2 has no lookbehind, so you cannot say “not preceded by example.”. You can enumerate what you do mean:

(?i)(prod|production|live)-db\.internal

2. Reorder with priority

Rules run in ascending priority, and a redact mutates the request in place, so later rules see the redacted text. That gives you a way to defuse a match before it reaches a block.

If a block rule is firing on text that a redaction would have made harmless, put the redaction first:

# 20: emails become [REDACTED]
vulnetix ai-firewall policy guardrail redact-pii \
  --rule-type pii_redact --action redact --priority 20 --enable

# 30: this now never sees a raw customer email, so it stops firing
vulnetix ai-firewall policy guardrail no-customer-data \
  --rule-type blocked_pattern --action block \
  --pattern '(?i)@customer\.example' --priority 30 --enable

This is not an allowlist. It is a sequencing trick, and it only works when a redaction genuinely removes the thing the block was worried about.

3. Step down the ladder

If a rule is producing noise you cannot pattern your way out of, demote it rather than delete it:

vulnetix ai-firewall policy guardrail noisy-rule --uuid <uuid> --action flag

You keep the visibility and stop the pain. A flag rule that fires 200 times a week is telling you something real about your organisation, even if you cannot enforce on it yet. See rollout.

The categories that generate the most noise

Prompt-injection patterns, by a wide margin. People discuss prompt injection — your security team does it daily, and every one of their messages contains the phrases you are matching on. If your AppSec channel runs through the firewall, expect these rules to fire constantly, and expect that to be correct behaviour. Consider running injection rules at flag permanently.

JWT and token shape patterns. Documentation, examples, test fixtures, and blog posts are full of example tokens. A pattern matching the shape of a JWT cannot tell a real one from eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0. in a tutorial.

The built-in card detector. It matches any 13-to-16-digit run and does not run a Luhn check, so long order numbers and numeric IDs will trip it.

What to do when you genuinely cannot pattern around it

Sometimes the string you must not leak is genuinely indistinguishable from a string your developers legitimately use. There is no clever answer to that within the firewall. Your real options are:

  • Accept the false positives and let people rephrase, if the cost of a leak is high enough.
  • Run the rule at flag and handle it as a detection problem rather than a prevention one.
  • Change the upstream thing — if a production identifier is being pasted into chats often enough to matter, the more durable fix is usually elsewhere.

Roadmap

An allowlist with mask-before-detect semantics — where an exempted phrase is masked out before rules run, so exempting one phrase does not blind the scanner to the rest of the message — is a design we like and do not have. It is on the roadmap, and it is not shipped today.