Model allow/deny

# Block one model everywhere it appears
vulnetix ai-firewall policy model gpt-4o --deny --any-provider

# Allow a specific model at a specific provider
vulnetix ai-firewall policy model gpt-4o-mini --allow --provider openai

# Remove an entry
vulnetix ai-firewall policy model gpt-4o --remove --provider openai

Exactly one of --allow, --deny, or --remove, and exactly one of --provider <slug> or --any-provider.

The allowlist-mode flip

Warning

The first allow entry for a provider changes how that provider behaves.

  • No entries at all → every model the provider offers is usable.
  • Only deny entries → everything is usable except what you denied.
  • One or more allow entries → the provider is now allowlist-only. Every model that is not explicitly allowed is refused.

There is no switch to enable this. Adding an allow entry is the switch.

This is the single most surprising behaviour in the product, so make it concrete:

# Before: your team can use any OpenAI model.
vulnetix ai-firewall policy model gpt-4o-mini --allow --provider openai
# After: your team can use gpt-4o-mini. Nothing else at OpenAI works.

That is usually what people want when they type it. It is occasionally a nasty surprise. Now you know.

An unlisted model in allowlist mode:

{
  "error": {
    "message": "model gpt-4o is not in the organisation allowlist",
    "type": "policy_violation",
    "code": "model_not_allowed"
  }
}

A denied model, in either mode:

{
  "error": {
    "message": "model gpt-4o is denied by organisation policy",
    "type": "policy_violation",
    "code": "model_denied"
  }
}

Deny list or allowlist?

A deny list is right when you have a specific problem: one model is too expensive, or has a licence you cannot accept, or is deprecated and you want people off it. Everything else keeps working. Low friction, low assurance.

An allowlist is right when you need to know what your organisation is running. Nothing works unless you approved it. High assurance, and it will generate tickets every time a new model ships — which is either the point, or the reason not to do it.

Most organisations start with a deny list and move to an allowlist for the providers that matter.

The scenario this is for

An agent framework updates and starts defaulting to a more capable, much more expensive model. Nobody chose this. The first anyone hears about it is the invoice.

vulnetix ai-firewall policy model gpt-4o-mini --allow --provider openai

OpenAI is now allowlist-only. The framework’s silent upgrade gets a clean 403 naming the policy, instead of a bill.

The same lever constrains coding agents, which are the most enthusiastic consumers of whatever model they are pointed at.

--any-provider

The same model is often reachable through several vendors — gpt-4o directly from OpenAI, and also through OpenRouter. Denying it at one does nothing about the other.

vulnetix ai-firewall policy model gpt-4o --deny --any-provider

This expands into an entry per provider that lists the model, so the denial actually holds across all of them.

Note --any-provider is resolved against the model catalog at the time you run it. A provider that lists the model later is not covered retroactively. If you rely on this for a hard boundary, prefer denying the provider.

Model names are the provider’s names

The gateway passes the model string through verbatim, so the name you allow must be the name the provider uses:

ProviderThe string
openaigpt-4o-mini
openrouteropenai/gpt-4o-mini
anthropicclaude-sonnet-5

Allowing gpt-4o-mini at OpenRouter does nothing, because OpenRouter does not call it that.

Models the catalog does not know about

A model that is not in the catalog passes, unless the provider is in allowlist mode. That is deliberate: the catalog syncs hourly, and a model released this morning should not be an outage.

The consequence, which you should be clear-eyed about: a deny list cannot block a model that does not exist yet. Only an allowlist gives you that.

In policy as code

spec:
  models:
    - slug: gpt-4o-mini
      provider: openai
      action: allow

    - slug: claude-sonnet-5
      provider: anthropic
      action: allow

    - slug: gpt-4o
      anyProvider: true
      action: deny

See policy as code.