Block secrets

The most common thing an organisation wants from an LLM firewall is this: do not let a developer paste a production connection string into a chat window. That is a blocked_pattern rule with a block action.

vulnetix ai-firewall policy guardrail no-connection-strings \
  --rule-type blocked_pattern \
  --action block \
  --pattern '(?i)postgres://\S+' \
  --priority 10 \
  --enable

Now this request is refused:

“why does postgres://svc:hunter2@db.internal:5432/prod time out?”

{
  "error": {
    "message": "request blocked by AI firewall policy: content matched pattern for policy \"no-connection-strings\"",
    "type": "policy_violation",
    "code": "request_blocked",
    "blocked_by": "no-connection-strings"
  }
}

And this one is not:

“why would a postgres connection from our service time out?”

The developer still gets their answer. The credential never left.

Tip Ship it as --action flag first. Run it for a week, look at what it actually caught, then switch it to block. A block rule that fires on legitimate work gets the whole firewall switched off. See rollout.

Why block rather than redact

For a secret, block is almost always right and redact almost always wrong.

Redaction rewrites the match to [REDACTED] and lets the request through — so the developer gets a useless answer about a redacted string, and does not know why. They will assume the model is being unhelpful and rephrase until it works, possibly around your rule.

A block is loud. It names the rule that fired. The developer learns the policy exists in the moment it matters. Save redact for data the model does not need in order to be useful — which is what PII redaction is for.

A pattern library

These are starting points, not a finished policy. Test each one against your own traffic at flag before you block on it — every organisation has legitimate text that looks like a secret.

Database connection strings

(?i)(postgres|postgresql|mysql|mongodb(\+srv)?|redis|amqp)://[^\s'"]+:[^\s'"]+@

Requires a user:password@ to be present, so it fires on credentialed URLs and not on postgres://localhost/dev.

Cloud provider keys

AKIA[0-9A-Z]{16}

AWS access key ID.

AIza[0-9A-Za-z_\-]{35}

Google API key.

Private keys and certificates

-----BEGIN [A-Z ]*PRIVATE KEY-----

The single highest-value, lowest-false-positive rule on this page. There is no legitimate reason for a private key to be in a prompt.

Tokens

gh[pousr]_[0-9A-Za-z]{36,}

GitHub personal access, OAuth, user-to-server, server-to-server, and refresh tokens.

xox[baprs]-[0-9A-Za-z\-]{10,}

Slack tokens.

sk-[A-Za-z0-9]{20,}

OpenAI-style provider keys. Worth blocking: a developer pasting a provider key into a prompt is both a leak and a sign they have misunderstood the two keys.

eyJ[A-Za-z0-9_\-]{10,}\.eyJ[A-Za-z0-9_\-]{10,}\.

A JWT. Note this matches the shape, so it will catch example tokens in documentation too — a good candidate for flag rather than block.

Internal infrastructure

(?i)[\w.\-]+\.(internal|corp|local|intranet)\b

Adjust the suffixes to your own naming. This one is about not leaking your network topology into a third party’s logs. Usually a flag, sometimes a redact.

Composing with priority

Rules run lowest priority first, and a block short-circuits. So put your highest-confidence, highest-severity rules at the lowest numbers:

vulnetix ai-firewall policy guardrail no-private-keys \
  --rule-type blocked_pattern --action block \
  --pattern '-----BEGIN [A-Z ]*PRIVATE KEY-----' --priority 1 --enable

vulnetix ai-firewall policy guardrail no-connection-strings \
  --rule-type blocked_pattern --action block \
  --pattern '(?i)(postgres|mysql)://[^\s]+:[^\s]+@' --priority 10 --enable

vulnetix ai-firewall policy guardrail flag-internal-hosts \
  --rule-type blocked_pattern --action flag \
  --pattern '(?i)[\w.\-]+\.(internal|corp)\b' --priority 50 --enable

Regex caveats

Patterns are RE2. There is no lookahead, no lookbehind, and no backreferences — by design, because RE2 cannot be made to hang on a hostile input. If you are porting patterns from a secret scanner that uses PCRE, some will not compile.

A rule whose pattern does not compile is silently skipped. It will sit in your policy looking enabled and enforce nothing. This is exactly why vulnetix ai-firewall status compiles your patterns locally and reports guardrail_pattern_invalid — run it after any rule change.

See the regex reference.

  • Regex reference — the RE2 subset, and why.
  • Rollout — flag → redact → block.
  • Tuning false positives — when a block rule is too eager.
  • vulnetix secret-scan — catching secrets in the repository, before they ever reach a prompt. The firewall is the last line, not the first.