Skip to content

fix(security): match virtual auto/* and qtSd/* routes against a key's combo allow-list (GHSA-7j4q-6gx6-pg77) - #15072

Merged
diegosouzapw merged 1 commit into
release/v3.8.51from
fix/auto-combo-allowlist
Sep 29, 2026
Merged

diegosouzapw merged 1 commit into
release/v3.8.51from
fix/auto-combo-allowlist

Conversation

@diegosouzapw

Copy link
Copy Markdown
Collaborator

⚠️ base-red inherited: #15032

Fixes GHSA-7j4q-6gx6-pg77. Reported, reproduced and fixed by @aldoeliacim; this PR lands the patch and regression test from the advisory, with credit.

Problem

isComboAllowedForKey() resolves the requested model to a persisted combo row. The built-in virtual routes auto/* and qtSd/* dispatch like combos, but they are not persisted, so the lookup returned null. That was read as "not a combo, allowed".

As a result, a key restricted to allowedCombos: ["my-combo"] could still reach every connected provider through auto/coding, auto/fast and auto/cheap, including paid OAuth subscription accounts. The route was also reachable through /v1/messages. #13670's allowAutoCombos is an opt-out that defaults to allowed, so it did not close this.

Fix (fail closed)

When no persisted combo matches, a virtual route falls back to its own name as the combo name. It is then denied unless the key's allow-list grants it, either through the combo/* wildcard or an explicit entry. Unrestricted and wildcard keys are unaffected, and allowAutoCombos: false still applies on top. The model-restriction branch reuses the same isVirtualComboModel() helper.

Validation

  • New test restricted combo keys cannot dispatch virtual auto routes:
    • auto/coding|fast|cheap is denied for a named-combo key, a deny-all key and an opted-out key;
    • it is allowed for a combo/* key;
    • direct models stay unaffected.
    • It fails on the old code (auto/coding allowed).
  • api-key-policy passes all 44 tests. The API-key and combo-access suites run on 192.168.0.113; results are in a comment below.

… combo allow-list (GHSA-7j4q-6gx6-pg77)

isComboAllowedForKey() resolved the requested model to a persisted combo row.
Built-in virtual routes (auto/*, qtSd/*) dispatch like combos but are not
persisted, so the lookup returned null — read as "not a combo, allowed". A
key restricted to allowedCombos: ["my-combo"] could therefore reach every
connected provider through auto/coding, auto/fast, auto/cheap, including
paid OAuth subscription accounts.

Virtual routes now fall back to their own name as the combo name, so they are
denied unless the key's allow-list grants them (the combo/* wildcard or an
explicit entry). Unrestricted keys are unaffected and allowAutoCombos (#13670)
still applies on top. The model-restriction branch reuses the same helper.

Test fails on the old code (auto/coding allowed for a restricted key).

Co-authored-by: Aldo <17973757+aldoeliacim@users.noreply.github.com>
@diegosouzapw

Copy link
Copy Markdown
Collaborator Author

Validation on 192.168.0.113 (2434554): api-key-policy 44/44, api-key-allow-auto-combos 8/8, api-key-policy-noauth-allowed-connections 5/5, models-catalog-combo-access 6/6, api-keys-allowed-combos-preserve-12267 5/5, migration-149-api-key-combo-access 1/1, noauth-autocombo-allowlist 3/3, combo-account-allowlist-3266 8/8, auto-combo-candidates-free-access-reason 3/3. typecheck:core 0 errors. File-size, complexity and stryker coverage are OK.

@diegosouzapw
diegosouzapw merged commit 93f5520 into release/v3.8.51 Sep 29, 2026
16 of 21 checks passed
@diegosouzapw
diegosouzapw deleted the fix/auto-combo-allowlist branch October 18, 2026 23:50
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.

1 participant