Skip to content

fix(modelcatalog): wildcard allow-list permits any model on custom providers#4535

Open
mickgvirtu wants to merge 1 commit into
maximhq:devfrom
mickgvirtu:pr-wildcard-custom-provider
Open

fix(modelcatalog): wildcard allow-list permits any model on custom providers#4535
mickgvirtu wants to merge 1 commit into
maximhq:devfrom
mickgvirtu:pr-wildcard-custom-provider

Conversation

@mickgvirtu

Copy link
Copy Markdown

Summary

With a virtual-key allow-list of ["*"] ("All models"), IsModelAllowedForProvider still cross-checks the model against the catalog via GetProvidersForModel. For a custom (OpenAI-compatible) provider the catalog can't enumerate the backend's models, so legitimate models the operator pointed the provider at are wrongly denied with model_blocked.

Changes

  • For a custom provider, ["*"] now means "all models on this provider" (returns true). Native providers stay catalog-cross-checked, so a wildcard can't spray a model to a provider that doesn't serve it.
  • Removed a stale doc comment describing the old list-models-disabled fast path.
  • Safety: this runs after the governance blacklist (BlacklistedModels.IsBlocked, which wins over the allow-list), so a wildcard does not bypass explicit denials.

Type of change

  • Bug fix

Affected areas

  • Core (Go)

How to test

go test ./framework/modelcatalog/

New models_test.go covers: wildcard+custom+uncatalogued ⇒ allow; wildcard+native+unserved ⇒ deny; empty ⇒ deny; explicit match.

@CLAassistant

CLAassistant commented Jun 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d54fd4f0-5f3c-457f-a723-13042e09675f

📥 Commits

Reviewing files that changed from the base of the PR and between 3e052a2 and 0be8be1.

📒 Files selected for processing (3)
  • docs/architecture/framework/model-catalog.mdx
  • framework/modelcatalog/models.go
  • framework/modelcatalog/models_test.go
✅ Files skipped from review due to trivial changes (1)
  • docs/architecture/framework/model-catalog.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • framework/modelcatalog/models.go
  • framework/modelcatalog/models_test.go

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Updated model allowance behavior for wildcard ("*") allow-lists: custom providers now allow any model unconditionally, while native providers still require the model to be served by a provider listed in the catalog.
  • Tests

    • Added coverage for allow/deny behavior, including wildcard vs empty allow-lists and native vs custom provider handling.
  • Documentation

    • Clarified wildcard ("*") behavior differences for native versus custom providers.

Walkthrough

IsModelAllowedForProvider in framework/modelcatalog/models.go is updated so that a wildcard allow-list ("*") on a custom provider unconditionally allows all models, replacing the prior check that gated on whether ListModels was disabled. The documentation is clarified to distinguish this behavior from native providers, which remain subject to catalog lookup. A new test file pins five allow/deny scenarios for this function.

Changes

Custom provider wildcard allow-list behavior and test coverage

Layer / File(s) Summary
Wildcard allow-list logic for custom providers
framework/modelcatalog/models.go
Removes the hasListModelsEndpointDisabled condition for custom providers under a wildcard allow-list; any providerConfig with a non-nil CustomProviderConfig now unconditionally passes. Native providers still require GetProvidersForModel(model) membership. Updated comment documents this behavior.
Documentation of wildcard behavior distinction
docs/architecture/framework/model-catalog.mdx
Updates the IsModelAllowedForProvider documentation to clarify that wildcard ("*") behavior differs between custom providers (unconditional allowance) and native providers (catalog-determined via GetProvidersForModel).
Test helpers and imports
framework/modelcatalog/models_test.go
Adds the test file with required imports, then introduces emptyCatalog() and customProviderConfig() helpers that enable testing without pre-populating catalog data.
Test scenarios for allow/deny logic
framework/modelcatalog/models_test.go
Adds five test functions covering wildcard-on-custom-provider (allows uncatalogued models), wildcard-on-native-unserved (denies), wildcard-on-native-served (allows), empty-allow-list (denies both provider types), and explicit-match (permits only listed model names).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • maximhq/bifrost#4124: Directly modifies the same IsModelAllowedForProvider wildcard (allowedModels.IsUnrestricted() / "*") path in framework/modelcatalog/models.go, introducing the catalog-opaque logic for custom providers that this PR further refines.

Suggested reviewers

  • akshaydeo
  • danpiths

Poem

🐇 Hop, hop, the wildcard's free,
No ListModels gate to bother me!
Custom providers skip the check,
While native ones still dot the spec.
Five tests now guard the den—
The catalog bunny grins again! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing wildcard allow-lists for custom providers in the model catalog.
Description check ✅ Passed The description covers all critical sections from the template including summary, changes, type of change, affected areas, how to test, and related safety considerations.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot requested review from akshaydeo and danpiths June 18, 2026 15:09
@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — the change is minimal, targeted, and the blacklist-before-allowlist ordering is preserved across all three governance call sites.

The wildcard fast-path for custom providers is correct: the catalog genuinely cannot enumerate a custom backend's models, so deferring to it was never the right call. The blacklist pre-check in main.go, utils.go, and resolver.go all run before IsModelAllowedForProvider, so a wildcard cannot bypass explicit denials. The new tests cover wildcard+custom allow, wildcard+native served/unserved, empty deny-all, and explicit-list match — all the meaningful branches of the function.

No files require special attention.

Important Files Changed

Filename Overview
framework/modelcatalog/models.go Removes the hasListModelsEndpointDisabled flag and widens the custom-provider wildcard fast-path to all custom providers; blacklist pre-check in all three governance call sites runs before this function, so the wildcard cannot bypass explicit denials.
framework/modelcatalog/models_test.go Good behavioral coverage for all four cases (wildcard+custom, wildcard+native served/unserved, empty deny, explicit match); tests are flat functions rather than table-driven, which is the repo-preferred style for behavior changes.
docs/architecture/framework/model-catalog.mdx Doc updated to reflect custom-vs-native wildcard semantics; accurate with respect to the new code.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[IsModelAllowedForProvider called] --> B{allowedModels.IsUnrestricted?}
    B -- No --> C{allowedModels.IsEmpty?}
    C -- Yes --> D[return false deny-all]
    C -- No --> E[Explicit list match\ndirect or provider-prefixed]
    E --> F[return true/false]
    B -- Yes --> G{isCustomProvider?\nproviderConfig.CustomProviderConfig != nil}
    G -- Yes --> H[return true\nwildcard = all models on custom backend]
    G -- No --> I[GetProvidersForModel model\ncatalog cross-check]
    I --> J{provider in result?}
    J -- Yes --> K[return true]
    J -- No --> L[return false]

    style H fill:#90EE90
    style D fill:#FFB6C1
    style L fill:#FFB6C1
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[IsModelAllowedForProvider called] --> B{allowedModels.IsUnrestricted?}
    B -- No --> C{allowedModels.IsEmpty?}
    C -- Yes --> D[return false deny-all]
    C -- No --> E[Explicit list match\ndirect or provider-prefixed]
    E --> F[return true/false]
    B -- Yes --> G{isCustomProvider?\nproviderConfig.CustomProviderConfig != nil}
    G -- Yes --> H[return true\nwildcard = all models on custom backend]
    G -- No --> I[GetProvidersForModel model\ncatalog cross-check]
    I --> J{provider in result?}
    J -- Yes --> K[return true]
    J -- No --> L[return false]

    style H fill:#90EE90
    style D fill:#FFB6C1
    style L fill:#FFB6C1
Loading

Reviews (3): Last reviewed commit: "modelcatalog: wildcard allow-list permit..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
framework/modelcatalog/models_test.go (1)

45-55: ⚡ Quick win

Add the positive native wildcard case.

This only proves wildcard denies unserved native models. Since the PR preserves native catalog cross-checking, add a seeded native-provider model case that must return true; otherwise, a regression that denies all native wildcard requests would still pass.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/modelcatalog/models_test.go` around lines 45 - 55, The test
TestIsModelAllowedForProvider_WildcardNativeProviderUnserved only validates the
negative case where a wildcard denies an unserved model. Add a complementary
positive test case that seeds the catalog with a model served by a native
provider (such as OpenAI) and verifies that IsModelAllowedForProvider returns
true when called with a wildcard for that same provider and model. This ensures
the code correctly allows wildcards for native providers when models are
properly served, preventing regressions where all native wildcard requests might
be incorrectly denied.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@framework/modelcatalog/models_test.go`:
- Around line 45-55: The test
TestIsModelAllowedForProvider_WildcardNativeProviderUnserved only validates the
negative case where a wildcard denies an unserved model. Add a complementary
positive test case that seeds the catalog with a model served by a native
provider (such as OpenAI) and verifies that IsModelAllowedForProvider returns
true when called with a wildcard for that same provider and model. This ensures
the code correctly allows wildcards for native providers when models are
properly served, preventing regressions where all native wildcard requests might
be incorrectly denied.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 794c8382-74f6-4e2b-8a5e-4548a3c66474

📥 Commits

Reviewing files that changed from the base of the PR and between 96bb2bd and ef70510.

📒 Files selected for processing (2)
  • framework/modelcatalog/models.go
  • framework/modelcatalog/models_test.go

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
@mickgvirtu

Copy link
Copy Markdown
Author

Thanks — both addressed:

  • Positive native-wildcard case (coderabbit): added TestIsModelAllowedForProvider_WildcardNativeProviderServed — seeds a native provider (OpenAI) with gpt-4o via the live store and asserts a wildcard allows it. Guards against a regression that denied all native wildcard requests.
  • Stale docs (greptile): updated docs/architecture/framework/model-catalog.mdx — the wildcard behavior section + inline example now describe the custom-vs-native asymmetry (custom ⇒ allow-all; native ⇒ catalog cross-check) instead of "always delegates to the catalog".

go test ./framework/modelcatalog/ passes (custom-allow, native-served-allow, native-unserved-deny, empty-deny, explicit-match).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/architecture/framework/model-catalog.mdx (1)

292-298: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix example call signature to match implementation

At Line 294, the docs call IsModelAllowedForProvider with 3 args, but the current method takes 4 args (providerConfig before allowedModels). This example is currently copy/paste incorrect.

Suggested docs patch
 isAllowed := modelCatalog.IsModelAllowedForProvider(
     schemas.OpenRouter,
     "gpt-4o",
-    schemas.WhiteList{"*"}, // wildcard = check catalog
+    nil, // providerConfig (nil for native provider example)
+    schemas.WhiteList{"*"}, // wildcard = check catalog
 )

As per coding guidelines, docs under docs/** should maintain parity with code behavior/contracts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture/framework/model-catalog.mdx` around lines 292 - 298, The
example call to IsModelAllowedForProvider in the documentation is incorrect - it
currently passes 3 arguments but the actual method signature requires 4
arguments with providerConfig appearing before allowedModels. Update the example
code snippet to include the missing providerConfig argument and reorder the
parameters to match the actual method implementation signature for
IsModelAllowedForProvider.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@docs/architecture/framework/model-catalog.mdx`:
- Around line 292-298: The example call to IsModelAllowedForProvider in the
documentation is incorrect - it currently passes 3 arguments but the actual
method signature requires 4 arguments with providerConfig appearing before
allowedModels. Update the example code snippet to include the missing
providerConfig argument and reorder the parameters to match the actual method
implementation signature for IsModelAllowedForProvider.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f7156ed-9cbc-4e2b-9552-fc299a258d9e

📥 Commits

Reviewing files that changed from the base of the PR and between ef70510 and 3e052a2.

📒 Files selected for processing (3)
  • docs/architecture/framework/model-catalog.mdx
  • framework/modelcatalog/models.go
  • framework/modelcatalog/models_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • framework/modelcatalog/models.go

IsModelAllowedForProvider: a ["*"] (All models) virtual-key allow-list permits any model on a
custom (OpenAI-compatible) provider, whose backend the catalog can't enumerate. Native providers
stay catalog-cross-checked so a wildcard can't spray a model to a provider that doesn't serve it.
Fixes spurious model_blocked 403s on internal models (e.g. glm) on custom providers. Adds unit
tests for the custom/native asymmetry, empty deny-by-default, and explicit matching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mickgvirtu mickgvirtu force-pushed the pr-wildcard-custom-provider branch from 3e052a2 to 0be8be1 Compare June 21, 2026 18:23
@mickgvirtu

Copy link
Copy Markdown
Author

Rebased onto transports/v1.5.16 to keep current with dev. No conflicts (framework/modelcatalog/ was unchanged this release); go test ./framework/modelcatalog/ passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants