Provider allow/deny
vulnetix ai-firewall policy provider deepseek --deny # nobody may use it
vulnetix ai-firewall policy provider openai --allow # explicitly approved
vulnetix ai-firewall policy provider mistral --clear # back to the default
Exactly one of --allow, --deny, or --clear per command.
The three states
| State | Meaning |
|---|---|
| no entry (the default) | Usable. Anyone in the organisation can reach it. |
allow | Usable — and explicitly recorded as approved. |
deny | Every request through this provider is refused with a 403. |
The default is permissive. A provider you have never touched is allowed, not blocked. There is no global default-deny switch.
If your posture is “only approved vendors”, you must explicitly deny the ones you have not approved. Put the complete list in a policy file so it is reviewable and so nobody has to remember which providers exist.
allow vs. no entry
Functionally, both permit traffic. The difference is intent.
An explicit allow records a decision. It says someone looked at this vendor and
approved it — which is what you want when an auditor asks how the list was arrived
at, and what makes a later “why is this allowed?” answerable.
A missing entry says only that nobody has thought about it yet.
What a denied request looks like
{
"error": {
"message": "provider deepseek is denied by organisation policy",
"type": "policy_violation",
"code": "provider_denied"
}
}
403, in the dialect of whatever client asked. It does not matter which developer,
which machine, which project, or which agent — a denied provider is denied.
Denial is checked before the guardrails run, so a denied provider costs nothing to enforce.
The scenario this is for
Your DPA does not cover a vendor. Somebody adds them to a side project anyway, because their model is good and the friction of asking was higher than the friction of not asking.
vulnetix ai-firewall policy provider together --deny
Now that path returns a clean 403 naming the policy, org-wide, immediately. The
developer discovers the constraint at the moment they hit it, rather than in a
quarterly review.
Watch out for routers
openrouter is a router. Allowing it grants access to models hosted by many
underlying vendors — and the firewall’s provider policy sees only openrouter.
If you are using provider policy to draw a jurisdictional or procurement boundary, an allowed OpenRouter is a hole in it. Either deny it, or constrain it with model policy, which can see the individual model IDs.
A provider with no key
A provider that is allowed but has no stored key in the vault returns a different
403:
{
"error": {
"message": "no OpenAI API key configured for your organisation: add one with 'vulnetix ai-firewall key set openai' or at https://www.vulnetix.com/vdb-ai-firewall#byok",
"type": "policy_violation",
"code": "provider_key_missing"
}
}
This is not a policy refusal — you are authenticated and permitted, there is simply no key to forward with. Store one: BYOK.
In policy as code
spec:
providers:
- slug: openai
action: allow
- slug: anthropic
action: allow
- slug: deepseek
action: deny
- slug: openrouter
action: deny
See policy as code. This is the right way to manage a vendor list: reviewed in a pull request, with a history of why each decision was made.
Seeing the current state
vulnetix ai-firewall status
Shows every provider in the catalog, your organisation’s policy for it, and whether a key is stored.
Related
- Provider catalog — the full list.
- Model allow/deny — the finer-grained lever.
- Jurisdictional control — using this to hold a data-residency boundary.