Providers & models

Provider and model policy decides what an organisation may call. It is evaluated before any guardrail runs, and a refusal here never reaches the provider at all.

Providers

A provider is in one of three states:

StateHowEffect
defaultno association (the initial state)usable, if a key is stored
allow--allowusable — an explicit pin, useful as documentation
deny--denyevery request returns 403 provider_denied
vulnetix ai-firewall policy provider openrouter --deny
vulnetix ai-firewall policy provider openai --allow
vulnetix ai-firewall policy provider openai --clear    # back to default

Default and allow behave identically today. The difference is intent: an explicit allow records that someone decided, which matters when you are reading a policy six months later, and it survives a future change to what “default” means.

A provider with no stored key is not usable whatever its policy says — the gateway has nothing to authenticate upstream with, and returns provider_key_missing. See BYOK.

Models

vulnetix ai-firewall policy model gpt-4o --provider openai --allow
vulnetix ai-firewall policy model gpt-3.5-turbo --provider openai --deny
vulnetix ai-firewall policy model claude-sonnet-4-5 --any-provider --allow
vulnetix ai-firewall policy model gpt-4o --provider openai --remove

Exactly one of --provider <slug> or --any-provider is required.

--any-provider expands, at the moment you run it, to every provider whose catalog currently lists that model slug. It is not a standing rule: a provider added to the catalog next month, or one that starts offering the model later, is not covered retroactively. Re-run the command if you want them included.

The allowlist flip

Important The first --allow entry for a provider turns that provider allowlist-only. From then on, any model that is not on the allow list is refused with model_not_allowed — even though nobody denied it.

Worked through:

# Nothing configured. Every model OpenAI offers is usable.
curl .../chat/completions -d '{"model":"gpt-4o", ...}'          # 200
curl .../chat/completions -d '{"model":"gpt-4o-mini", ...}'     # 200

# Deny one model. Only that model is blocked.
vulnetix ai-firewall policy model gpt-3.5-turbo --provider openai --deny
curl .../chat/completions -d '{"model":"gpt-4o", ...}'          # 200
curl .../chat/completions -d '{"model":"gpt-3.5-turbo", ...}'   # 403 model_denied

# Allow one model. OpenAI is now allowlist-only.
vulnetix ai-firewall policy model gpt-4o --provider openai --allow
curl .../chat/completions -d '{"model":"gpt-4o", ...}'          # 200
curl .../chat/completions -d '{"model":"gpt-4o-mini", ...}'     # 403 model_not_allowed  ← never denied

That last line is the one that catches people. gpt-4o-mini was working, nobody touched it, and it stopped — because someone allowed a different model.

This is a deliberate design: an allowlist that only takes effect once you have also denied everything else would not be an allowlist. But it is surprising, so:

  • vulnetix ai-firewall status flags any wired client whose pinned model would be refused this way, and says explicitly that the provider is in allowlist mode.
  • vulnetix ai-firewall install --model <slug> refuses to pin a model the policy would reject, rather than writing it and letting you discover the 403 later.

To leave allowlist mode, remove every allow entry for that provider:

vulnetix ai-firewall policy model gpt-4o --provider openai --remove

Model discovery

GET /v1/models through the gateway is filtered by policy. A client that autodiscovers models — and most agent frameworks do — only ever sees models it is permitted to call, so it will not offer your users a model that would 403 on first use.

Reading the current policy

vulnetix ai-firewall get
vulnetix ai-firewall get -o json

Or serialise it to a file you can review and commit — see policy as code:

vulnetix ai-firewall export

Flags

policy provider <slug>

FlagMeaning
--allowExplicitly allow the provider
--denyDeny it org-wide
--clearRemove the association (back to default)

policy model <slug>

FlagMeaning
--allowAdd to the allow list (puts the provider into allowlist mode)
--denyAdd to the deny list
--removeRemove the entry
--provider <slug>Scope to one provider
--any-providerExpand across every provider currently listing this model

Both also accept --base-url and -o {pretty,json}.

Note These commands are also spelled vulnetix config set ai-firewall provider and ... model. Both spellings run the same code; the config form is kept because scripts use it.