forked from ding113/claude-code-hub
-
Notifications
You must be signed in to change notification settings - Fork 0
Support wildcard/regex model redirects and honor them in provider selection #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
h7ml
wants to merge
5
commits into
main
Choose a base branch
from
codex/add-model-redirection-support-for-regex
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import { describe, expect, test } from "vitest"; | ||
| import { ModelRedirector } from "@/app/v1/_lib/proxy/model-redirector"; | ||
| import type { Provider } from "@/types/provider"; | ||
|
|
||
| function buildProvider(modelRedirects: Record<string, string>): Provider { | ||
| return { | ||
| id: 1, | ||
| name: "test-provider", | ||
| providerType: "claude", | ||
| isEnabled: true, | ||
| weight: 1, | ||
| priority: 0, | ||
| costMultiplier: 1, | ||
| groupTag: null, | ||
| modelRedirects, | ||
| } as Provider; | ||
| } | ||
|
|
||
| describe("ModelRedirector pattern matching", () => { | ||
| test("matches wildcard patterns", () => { | ||
| const provider = buildProvider({ | ||
| "gpt-4o-*": "claude-sonnet-4", | ||
| }); | ||
|
|
||
| expect(ModelRedirector.getRedirectedModel("gpt-4o-mini", provider)).toBe("claude-sonnet-4"); | ||
| expect(ModelRedirector.hasRedirect("gpt-4o-mini", provider)).toBe(true); | ||
| }); | ||
|
|
||
| test("matches regex patterns", () => { | ||
| const provider = buildProvider({ | ||
| "/^gpt-4o-(mini|preview)$/": "claude-sonnet-4", | ||
| }); | ||
|
|
||
| expect(ModelRedirector.getRedirectedModel("gpt-4o-mini", provider)).toBe("claude-sonnet-4"); | ||
| expect(ModelRedirector.getRedirectedModel("gpt-4o-preview", provider)).toBe("claude-sonnet-4"); | ||
| expect(ModelRedirector.hasRedirect("gpt-4o-preview", provider)).toBe(true); | ||
| }); | ||
|
|
||
| test("falls back when regex is invalid", () => { | ||
| const provider = buildProvider({ | ||
| "/[invalid/": "claude-sonnet-4", | ||
| "claude-haiku": "claude-sonnet-4", | ||
| }); | ||
|
|
||
| expect(ModelRedirector.getRedirectedModel("claude-haiku", provider)).toBe("claude-sonnet-4"); | ||
| expect(ModelRedirector.hasRedirect("claude-haiku", provider)).toBe(true); | ||
| expect(ModelRedirector.getRedirectedModel("gpt-4o-mini", provider)).toBe("gpt-4o-mini"); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
JavaScript ReDoS protection libraries 2025💡 Result:
JavaScript ReDoS protection libraries (practical options in/around 2025)
1) Switch to a non-backtracking regex engine (strongest runtime protection)
re2(node-re2): Native Node.js bindings to Google’s RE2; avoids catastrophic backtracking but does not support some JS regex features (notably lookarounds and backreferences). [1]re2-wasm: Runs RE2 via WebAssembly (useful when native addons are undesirable); same “safe engine” idea and similar feature tradeoffs. [2][3]2) Detect risky regexes (CI/lint/test-time controls)
redos-detector: Library/CLI that scores how vulnerable a pattern is (browser/Node/Deno). [4]safe-regex2: Maintained fork ofsafe-regex; fast heuristic (“star height”) check—expects false positives/negatives (good as a cheap first pass). [5]safe-regex: Original package (widely used but older; same heuristic limitations). [6]vuln-regex-detector/davisjam/vuln-regex-detector: Heavier-weight detection aimed at finding real catastrophic-backtracking cases (includes project scanning workflow; testing can be expensive). [7][8]3) Operational mitigations you should still do
Even with tooling, also apply input length limits and avoid building regexes directly from untrusted input. [9]
Notes on RE2 compatibility: if you plan to move patterns to RE2, many constructs are intentionally avoided/unsupported (e.g., lookarounds, backreferences). [1][10]
Sources:
[1]
re2(node-re2) package info on RE2 safety + unsupported features [2]re2-wasmnpm [3] google/re2-wasm repo [4]redos-detectornpm [5]safe-regex2npm [6]safe-regexnpm [7]vuln-regex-detectornpm [8] davisjam/vuln-regex-detector GitHub [9] Bearer rule guidance on ReDoS mitigations [10] OWASP CRS note on non-backtracking/RE2-compatible regex constraints🌐 Web query:
regular expression denial of service prevention techniques Node.js💡 Result:
ReDoS prevention techniques in Node.js (practical checklist)
Avoid “evil” patterns in the first place
Constrain what the regex has to process
{1,25}) as part of input validation guidance. [2].*/.+when possible.Use a linear-time regex engine for untrusted regexes (or high-risk matches)
re2(node-re2) package; it avoids catastrophic backtracking by using a non-backtracking engine (with feature tradeoffs like no lookaheads/backreferences). [3]Detect risky regexes in CI / code review
safe-regex2to flag potentially catastrophic patterns (useful, but it can have false positives/negatives). [4]Put regex work behind a “circuit breaker”
Sources: OWASP Node.js Security Cheat Sheet [1], OWASP Input Validation Cheat Sheet [2],
re2/node-re2 docs [3],safe-regex2docs [4], V8 non-backtracking RegExp engine blog [5].🏁 Script executed:
Repository: dext7r/claude-code-hub
Length of output: 3456
🏁 Script executed:
Repository: dext7r/claude-code-hub
Length of output: 1478
🏁 Script executed:
Repository: dext7r/claude-code-hub
Length of output: 764
🏁 Script executed:
Repository: dext7r/claude-code-hub
Length of output: 48
🏁 Script executed:
Repository: dext7r/claude-code-hub
Length of output: 833
ReDoS 风险:管理员配置的正则模式可导致事件循环阻塞。
虽然
modelRedirects来自供应商配置而非终端用户 HTTP 请求(降低了攻击面),但恶意或失误的正则表达式(如/(a+)+$/)仍可在regexPattern.test(originalModel)执行时触发灾难性回溯,阻塞事件循环。现有的 try-catch 仅捕获语法错误,无法阻止计算复杂度攻击。建议在
parseRegexPattern中添加长度限制,这是业界公认的防护措施:修复方案:添加正则 body 长度上限
function parseRegexPattern(pattern: string): RegExp | null { if (!pattern.startsWith("/")) { return null; } const lastSlashIndex = pattern.lastIndexOf("/"); if (lastSlashIndex <= 0) { return null; } const body = pattern.slice(1, lastSlashIndex); const flags = pattern.slice(lastSlashIndex + 1); - if (!body) { + if (!body || body.length > 200) { return null; } try { return new RegExp(body, flags); } catch { return null; } }📝 Committable suggestion
🧰 Tools
🪛 ast-grep (0.40.5)
[warning] 26-26: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(body, flags)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
🤖 Prompt for AI Agents