Skip to content

feat: 添加 provider 模型获取功能#233

Closed
Kariseven323 wants to merge 9 commits intoding113:devfrom
Kariseven323:feat/fetch-provider-models
Closed

feat: 添加 provider 模型获取功能#233
Kariseven323 wants to merge 9 commits intoding113:devfrom
Kariseven323:feat/fetch-provider-models

Conversation

@Kariseven323
Copy link

@Kariseven323 Kariseven323 commented Nov 28, 2025

Summary

Add model fetching functionality to the provider settings page, allowing users to dynamically retrieve available models from the provider API without manual input.

功能概述

为 provider 设置页面添加了模型获取功能,用户可通过 API 动态获取可用模型列表,无需手动输入。

Problem

Previously, users had to manually input model names when configuring providers. This was error-prone and tedious, especially when providers have many available models or when model names change.

Solution

Implemented a "Fetch Models" button that queries the provider's /models endpoint to automatically retrieve and populate available models. The solution:

  • Supports multiple provider types (OpenAI-compatible, Claude, Gemini)
  • Handles different API authentication methods
  • Merges fetched models with existing selections (no duplicates)
  • Provides clear feedback on success/failure states

Changes

  • Added FetchModelsButton component supporting model list fetching from provider APIs
  • Integrated fetch models button into provider-form.tsx
  • Updated model-multi-select.tsx to dynamically load models and prioritize selected models in display order
  • Added fetchProviderModels server action with support for:
    • OpenAI-compatible / Codex: GET /v1/models
    • Claude / Claude-Auth: GET /v1/models (relay services)
    • Gemini / Gemini-CLI: GET /v1beta/models
  • Added complete i18n support (English & Chinese)
  • Fixed TypeScript type errors

主要变更

  • 新增 FetchModelsButton 组件,支持从 provider API 获取模型列表
  • provider-form.tsx 中集成模型获取按钮
  • 更新 model-multi-select.tsx,支持动态加载模型,优先显示已勾选模型
  • 添加完整的中英文国际化支持
  • 修复 TypeScript 类型错误

Testing

  • Tested with OpenAI-compatible providers
  • Tested with Claude relay services
  • Tested with Gemini API
  • Verified model merging with existing selections
  • Verified error handling for invalid URLs/keys
  • Verified i18n strings display correctly

Technical Details

  • New server action: fetchProviderModels in src/actions/providers.ts
  • New component: FetchModelsButton in provider forms
  • Uses existing proxy configuration for API requests
  • Supports both API key and JSON credentials authentication

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Kariseven323, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在增强提供商设置页面的功能,通过引入动态模型获取机制,用户现在可以直接从配置的提供商 API 获取可用的模型列表,而无需手动输入。这极大地简化了提供商的配置过程,提高了数据准确性,并确保了模型列表的实时性。

Highlights

  • 动态模型获取功能: 新增了“获取模型”功能,允许用户通过 API 动态获取可用模型列表,无需手动输入。
  • 新组件 FetchModelsButton: 引入了 FetchModelsButton 组件,用于触发模型获取操作,并处理其 UI 状态和逻辑。
  • 提供商表单集成: 在 provider-form.tsx 中集成了新的模型获取按钮,提升了用户在配置提供商时的体验。
  • 模型多选组件优化: 更新了 model-multi-select.tsx,使其能够支持动态加载的模型,并优化了排序逻辑,优先显示已选中的模型。
  • 后端模型获取逻辑: 在 src/actions/providers.ts 中实现了 fetchProviderModels 核心逻辑,支持多种供应商(OpenAI 兼容、Claude、Gemini)的模型 API 调用和响应解析。
  • 国际化支持: 为新功能添加了完整的中英文国际化支持,包括各种提示和状态信息。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ding113 ding113 added enhancement New feature or request size/M Medium PR (< 500 lines) size/L Large PR (< 1000 lines) labels Nov 28, 2025
@ding113
Copy link
Owner

ding113 commented Nov 28, 2025

📊 PR Size Analysis

This PR is Large (L) with 570 lines changed across 6 files.

Assessment

While this PR exceeds the typical "Medium" threshold (500 lines), the changes represent a single cohesive feature - adding model fetching functionality to providers. All components are interdependent:

File Purpose
messages/en/settings.json i18n strings (English)
messages/zh-CN/settings.json i18n strings (Chinese)
src/actions/providers.ts Backend API for fetching models
fetch-models-button.tsx New UI component
provider-form.tsx Integration wiring
model-multi-select.tsx Supporting updates

✅ Recommendation: No split needed

This is a well-organized single-feature PR. Splitting would actually increase review complexity since:

  • The backend API is meaningless without the UI
  • The UI component needs the i18n strings
  • All parts work together to complete the feature

The code is logically grouped and follows the project's patterns.


🤖 Automated analysis by Claude AI

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

此次 PR 新增了从供应商动态获取模型列表的功能,这是一个非常实用的改进,极大地提升了用户体验。整体实现很完整,包括了后端逻辑、前端组件和国际化支持,代码结构清晰。我在评审中发现了几点问题:一个关于 API 密钥日志记录的安全问题,一个关于 Gemini 凭证处理逻辑不完整的问题,以及两个可以提升代码健壮性和用户体验的小建议。修复这些问题将使新功能更加稳固和安全。

@ding113
Copy link
Owner

ding113 commented Nov 28, 2025

🔒 Security Scan Results

No security vulnerabilities detected

This PR has been scanned against OWASP Top 10, CWE Top 25, and common security anti-patterns. No security issues were identified in the code changes.

📋 Detailed Analysis

SSRF Protection ✅

The new fetchProviderModels function properly uses the existing validateProviderUrlForConnectivity function which:

  • Restricts protocols to HTTP/HTTPS only
  • Blocks internal network addresses (localhost, 127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 169.254.x.x)
  • Blocks IPv6 loopback and private addresses (::1, fe80:, fc00:, fd00:)
  • Blocks dangerous ports (22, 23, 25, 3306, 5432, 6379, 27017, 9200)

Authentication & Authorization ✅

  • Server action properly requires admin session: if (\!session || session.user.role \!== "admin")
  • Consistent with existing security patterns in the codebase
  • getUnmaskedProviderKey also requires admin authentication for key retrieval

Sensitive Data Handling ✅

  • API keys are NOT logged - only masked URL is logged: url.replace(/:\/\/[^@]*@/, "://***@")
  • No sensitive data exposure in error messages
  • Proper error handling without leaking internal details

Input Validation ✅

  • Proxy URL validation via isValidProxyUrl() - supports only http://, https://, socks5://, socks4://
  • URL validation on both client and server side
  • Type-safe TypeScript interfaces for all inputs

XSS Protection ✅

  • React components use proper JSX escaping (no dangerouslySetInnerHTML)
  • Toast messages use translated strings, not raw user input
  • No DOM manipulation with unsanitized data

Scanned Categories

  • ✅ Injection attacks (SQL, NoSQL, Command, LDAP, etc.)
  • ✅ Authentication and session management
  • ✅ Sensitive data exposure
  • ✅ Access control and authorization
  • ✅ Security misconfiguration
  • ✅ Cross-site scripting (XSS)
  • ✅ Insecure deserialization
  • ✅ SSRF and path traversal
  • ✅ Cryptographic weaknesses

🛡️ Security Posture

Strong - The implementation follows security best practices:

  1. Reuses existing security-hardened validation functions
  2. Proper admin-only authorization
  3. No sensitive data in logs or error messages
  4. Client and server-side validation
  5. Type-safe interfaces

🤖 Automated security scan by Claude AI - OWASP Top 10 & CWE coverage

Copy link
Owner

@ding113 ding113 left a comment

Choose a reason for hiding this comment

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

📋 Code Review Summary

This PR adds a provider model fetching feature with a new FetchModelsButton component and server-side fetchProviderModels action. The implementation is generally well-structured with proper i18n support and error handling. However, there are a few issues that should be addressed.

🔍 Issues Found

  • Critical (🔴): 0 issues
  • High (🟠): 1 issue
  • Medium (🟡): 2 issues
  • Low (🟢): 1 issue

🎯 Priority Actions

  1. [High] src/actions/providers.ts:2757-2762 - API key is exposed in URL query parameter for Gemini providers when isJsonCreds is false. This could lead to key exposure in logs, error messages, and HTTP Referer headers. Consider always using header-based authentication (x-goog-api-key header).

  2. [Medium] src/app/[locale]/settings/providers/_components/forms/fetch-models-button.tsx:119-121 - Error state is never reset back to "idle" unlike the success state which resets after 3 seconds. This leaves the button in a permanent error state until the page is refreshed or another fetch is attempted.

  3. [Medium] src/app/[locale]/settings/providers/_components/model-multi-select.tsx:163-173 - The sort function for prioritizing selected models doesn't maintain stable ordering. When aSelected === bSelected, it returns 0, which doesn't preserve alphabetical order within each group. Should use a.localeCompare(b) as a tiebreaker.

  4. [Low] src/app/[locale]/settings/providers/_components/forms/fetch-models-button.tsx:12 - The ProviderType import is used correctly, but the component receives values from the parent that include claude-auth, which works fine at runtime but could benefit from explicit type documentation.

💡 General Observations

  • The feature correctly reuses existing patterns like validateProviderUrlForConnectivity for SSRF prevention
  • Good separation of concerns between the button component and server action
  • Proper internationalization with both English and Chinese translations
  • The merge logic in onModelsLoaded correctly prevents duplicate models

🤖 Automated review by Claude AI - focused on identifying issues for improvement

@ding113 ding113 changed the base branch from main to dev November 28, 2025 16:23
@ding113
Copy link
Owner

ding113 commented Nov 28, 2025

请以 Dev 分支为基础进行 PR,非常感谢。

- 修复 logger.error 中 unknown 类型参数问题
- 为 isClientAbortError 添加类型检查
- 实现从 provider API 获取模型列表的功能
- 支持代理配置和错误处理
- 添加状态管理和用户反馈
- 注释本地化为中文,保留关键字英文
- 为 FetchModelsButton 组件添加中英文翻译
- 包含加载状态、成功和错误消息
- 在 provider-form.tsx 中添加模型获取按钮
- 更新 model-multi-select.tsx 支持动态模型加载
- 完善用户交互流程
- 修复 Gemini API key 日志脱敏 (key=xxx 参数)
- 修复错误状态不重置问题,3秒后自动恢复
- 修复空模型列表显示错误状态的问题
- 修复模型排序不稳定,添加字母顺序排序
- Gemini JSON 凭证返回明确错误提示
- parseModelsResponse 兼容对象数组格式
@Kariseven323 Kariseven323 force-pushed the feat/fetch-provider-models branch from 7962551 to 69ef863 Compare November 29, 2025 06:25
@ding113
Copy link
Owner

ding113 commented Nov 29, 2025

🔒 Security Scan Results

No security vulnerabilities detected

This PR has been scanned against OWASP Top 10, CWE Top 25, and common security anti-patterns. No security issues were identified in the code changes.

📋 OWASP Top 10 Coverage

  • A01: Injection - Clean (No SQL/NoSQL/Command injection vectors)
  • A02: Broken Authentication - Clean (Admin session required, proper auth check)
  • A03: Sensitive Data Exposure - Clean (API keys masked in logs)
  • A04: XML External Entities - N/A (No XML processing)
  • A05: Broken Access Control - Clean (Admin-only access enforced)
  • A06: Security Misconfiguration - Clean
  • A07: XSS - Clean (React auto-escaping, no dangerouslySetInnerHTML)
  • A08: Insecure Deserialization - Clean (Safe JSON parsing)
  • A09: Known Vulnerabilities - N/A (No new dependencies)
  • A10: Logging & Monitoring - Clean (Proper error logging)

🛡️ Detailed Security Analysis

SSRF Prevention ✅

The fetchProviderModels function properly uses validateProviderUrlForConnectivity() which implements comprehensive SSRF protections:

  • Blocks private IP ranges (127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 169.254.x.x)
  • Blocks IPv6 local addresses (::1, fe80:, fc00:, fd00:)
  • Blocks localhost
  • Blocks dangerous service ports (22, 23, 25, 3306, 5432, 6379, 27017, 9200)
  • Only allows http/https protocols
// src/actions/providers.ts:2624
const urlValidation = validateProviderUrlForConnectivity(data.providerUrl);

Authentication & Authorization ✅

Admin-only access properly enforced:

// src/actions/providers.ts:2617-2620
const session = await getSession();
if (!session || session.user.role !== "admin") {
  return { ok: false, error: "无权限执行此操作" };
}

Sensitive Data Handling ✅

API keys are properly masked before logging:

// src/actions/providers.ts:2672-2673
url: url.replace(/key=([^&]*)/gi, "key=***").replace(/:\/\/[^@]*@/, "://***@"),

Input Validation ✅

  • Provider URL validated via validateProviderUrlForConnectivity()
  • Proxy URL validated via isValidProxyUrl()
  • Protocol whitelist (http/https only for provider, plus socks for proxy)

Client-Side Validation ✅

Additional frontend validation in fetch-models-button.tsx:

if (!isValidUrl(providerUrl.trim()) || !/^https?:\/\//.test(providerUrl.trim())) {
  toast.error(t("invalidUrl"));
  return;
}

Scanned Categories

  • ✅ Injection attacks (SQL, NoSQL, Command, LDAP, etc.)
  • ✅ Authentication and session management
  • ✅ Sensitive data exposure
  • ✅ Access control and authorization
  • ✅ Security misconfiguration
  • ✅ Cross-site scripting (XSS)
  • ✅ Insecure deserialization
  • ✅ SSRF and path traversal
  • ✅ Cryptographic weaknesses

🛡️ Security Posture

Strong - The code follows established secure patterns in the codebase and properly leverages existing security utilities for URL validation and SSRF prevention.


🤖 Automated security scan by Claude AI - OWASP Top 10 & CWE coverage

Copy link
Owner

@ding113 ding113 left a comment

Choose a reason for hiding this comment

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

📋 Code Review Summary

This PR adds a "Fetch Models" feature to dynamically retrieve available models from provider APIs. The implementation is generally well-structured but has a critical issue with a missing import that will cause compilation failure.

🔍 Issues Found

  • Critical (🔴): 0 issues
  • High (🟠): 1 issue
  • Medium (🟡): 1 issue
  • Low (🟢): 0 issues

🎯 Priority Actions

  1. 🟠 High - Missing import in fetch-models-button.tsx: The component uses isValidUrl but does not import it. Add import { isValidUrl } from "@/lib/utils/validation"; at the top of the file.

  2. 🟡 Medium - Inconsistent error message hardcoding in fetchProviderModels: The server action uses hardcoded Chinese error messages (e.g., "无权限执行此操作", "未找到可用模型") instead of using i18n keys. This is inconsistent with the i18n pattern used in the UI component. Consider returning error codes that can be translated on the frontend.

💡 Detailed Issue Analysis

Issue 1: Missing Import (fetch-models-button.tsx:52)

File: src/app/[locale]/settings/providers/_components/forms/fetch-models-button.tsx
Line: 52 (where isValidUrl is called)

The component calls isValidUrl(providerUrl.trim()) on line 52, but the import statement is missing. Looking at similar components like api-test-button.tsx, this function should be imported from @/lib/utils/validation.

Suggested fix - Add this import after line 10:

import { isValidUrl } from "@/lib/utils/validation";

Issue 2: Hardcoded Chinese Error Messages (providers.ts:2626-2722)

File: src/actions/providers.ts
Lines: 2626, 2660, 2695, 2700, 2719, etc.

The fetchProviderModels server action returns hardcoded Chinese error messages:

  • Line 2626: "无权限执行此操作" (Unauthorized)
  • Line 2643: "代理地址格式无效..." (Invalid proxy format)
  • Line 2695: "获取模型列表失败: HTTP ${response.status}..." (Fetch failed)
  • Line 2700: "未找到可用模型" (No models found)
  • Line 2719: "请求超时..." (Request timeout)

While the frontend component properly uses i18n translations, the backend error messages are hardcoded. This creates an inconsistent user experience for non-Chinese users.

Suggested approach: Return error codes or standardized error keys that the frontend can translate, similar to how other parts of the codebase handle i18n errors.


🤖 Automated review by Claude AI - focused on identifying issues for improvement

@ding113
Copy link
Owner

ding113 commented Nov 29, 2025

🔒 Security Scan Results

No security vulnerabilities detected

This PR has been scanned against OWASP Top 10, CWE Top 25, and common security anti-patterns. No security issues were identified in the code changes.

Security Analysis Summary

🛡️ SSRF Protection - Well Implemented

The new fetchProviderModels function properly reuses the existing validateProviderUrlForConnectivity() function which includes:

  • Protocol validation (only HTTP/HTTPS allowed)
  • Internal network blocking (localhost, 127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, link-local addresses)
  • IPv6 internal address blocking (::1, fe80:, fc00:, fd00:)
  • Dangerous port blocking (22, 23, 25, 3306, 5432, 6379, 27017, 9200)

🔐 Authentication & Authorization - Properly Enforced

// Admin-only access check at the start of the function
const session = await getSession();
if (!session || session.user.role !== "admin") {
  return { ok: false, error: "无权限执行此操作", errorCode: "FETCH_MODELS_NO_PERMISSION" };
}

🔑 Sensitive Data Handling - Good Practices

  • API keys are masked in logs: url.replace(/key=([^&]*)/gi, "key=***").replace(/:\/\/[^@]*@/, "://***@")
  • Proxy URLs are sanitized via maskProxyUrl() before logging
  • Error messages don't expose sensitive internal details

✅ Input Validation

  • Provider URL validated with validateProviderUrlForConnectivity()
  • Proxy URL validated with isValidProxyUrl()
  • Protocol restrictions (http://, https://, socks4://, socks5://)
  • Client-side validation with isValidUrl() and protocol regex

✅ No Injection Risks

  • No SQL queries - uses typed ORM (Drizzle)
  • No command execution
  • No dynamic code evaluation
  • JSON parsing is type-safe with defined response types

✅ No XSS Risks

  • React components use standard JSX rendering (auto-escaped)
  • No dangerouslySetInnerHTML usage
  • No direct DOM manipulation with user input

Scanned Categories

  • ✅ Injection attacks (SQL, NoSQL, Command, LDAP, etc.)
  • ✅ Authentication and session management
  • ✅ Sensitive data exposure
  • ✅ Access control and authorization
  • ✅ Security misconfiguration
  • ✅ Cross-site scripting (XSS)
  • ✅ Insecure deserialization
  • ✅ SSRF and path traversal
  • ✅ Cryptographic weaknesses

📋 OWASP Top 10 Coverage

  • A01: Injection - Clean (no SQL/command injection vectors)
  • A02: Broken Authentication - Clean (admin role check)
  • A03: Sensitive Data Exposure - Clean (proper masking)
  • A04: XML External Entities - N/A (no XML processing)
  • A05: Broken Access Control - Clean (admin-only access)
  • A06: Security Misconfiguration - Clean
  • A07: XSS - Clean (React auto-escaping)
  • A08: Insecure Deserialization - Clean (typed JSON parsing)
  • A09: Known Vulnerabilities - N/A (no new dependencies)
  • A10: Logging & Monitoring - Clean (appropriate logging)

🛡️ Security Posture: Strong

The implementation follows security best practices and leverages existing security controls for URL validation and SSRF protection.


🤖 Automated security scan by Claude AI - OWASP Top 10 & CWE coverage

Copy link
Owner

@ding113 ding113 left a comment

Choose a reason for hiding this comment

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

📋 Code Review Summary

This PR adds a useful feature for dynamically fetching available models from provider APIs. The implementation covers multiple provider types (OpenAI-compatible, Claude, Gemini) with appropriate authentication handling. However, there are several issues related to error handling flow, unreachable code paths, and React best practices that should be addressed.

🔍 Issues Found

  • Critical (🔴): 0 issues
  • High (🟠): 2 issues
  • Medium (🟡): 3 issues
  • Low (🟢): 1 issue

🎯 Priority Actions

  1. Fix timeout error check ordering - The code logs timeout errors as generic errors before detecting they are timeouts, creating misleading log entries
  2. Fix unreachable code path in parseModelsResponse - The Array.isArray(data) check will never be true because data is typed as Record<string, unknown>
  3. Add specific error handling for Gemini JSON credentials - The thrown exception bypasses the i18n system and returns a confusing FETCH_MODELS_UNKNOWN error code
  4. Clean up setTimeout callbacks on unmount - Multiple timeout calls could cause state updates on unmounted components

💡 General Observations

  • The error handling structure is well-designed with error codes and localized messages, but the exception thrown in getModelsApiConfig creates an inconsistent flow
  • Consider adding unit tests for the parseModelsResponse function to verify all supported response formats work correctly
  • The pattern of clearing allowedModels when changing providerType (line 613) is a good UX improvement

🤖 Automated review by Claude AI - focused on identifying issues for improvement

@ding113
Copy link
Owner

ding113 commented Nov 29, 2025

📊 PR Size Analysis

This PR is Large (L) with 675 lines changed across 6 files.

Metric Value Threshold
Lines Changed 675 L: 500-1000
Files Changed 6 ✅ < 20

📝 Assessment

While this PR exceeds the typical medium PR size threshold, it represents a single cohesive feature (provider model fetching). The changes are well-organized:

Category Files Purpose
Backend src/actions/providers.ts Server action for fetching models
Frontend 3 UI components Form integration & model selection
i18n 2 message files English & Chinese translations

🔀 Potential Split (Optional)

If desired, this could be split into:

  1. PR 1: Backend + Core Component (~300 lines)

    • src/actions/providers.ts
    • src/app/[locale]/settings/providers/_components/forms/fetch-models-button.tsx
  2. PR 2: Integration + UI Updates (~200 lines)

    • src/app/[locale]/settings/providers/_components/forms/provider-form.tsx
    • src/app/[locale]/settings/providers/_components/model-multi-select.tsx
  3. PR 3: i18n (~175 lines)

    • messages/en/settings.json
    • messages/zh-CN/settings.json

✅ Verdict

Splitting is optional - The PR is large but focused on a single feature. If reviewers are comfortable reviewing it as-is, it can proceed. However, splitting would enable:

  • Faster review cycles
  • Easier rollback if issues arise
  • Better git history

🤖 Automated analysis by Claude AI

@ding113
Copy link
Owner

ding113 commented Nov 29, 2025

🔒 Security Scan Results

No security vulnerabilities detected

This PR has been scanned against OWASP Top 10, CWE Top 25, and common security anti-patterns. No security issues were identified in the code changes.

Scanned Categories

  • Injection attacks (SQL, NoSQL, Command, LDAP, etc.) - No dynamic query construction or shell command execution found
  • Authentication and session management - Proper admin role verification via getSession() before sensitive operations
  • Sensitive data exposure - API keys properly masked in logs (key=***, credentials redacted)
  • Access control and authorization - Admin-only check implemented for fetchProviderModels
  • Security misconfiguration - No debug flags or insecure defaults detected
  • Cross-site scripting (XSS) - React components use standard JSX patterns with auto-escaping
  • Insecure deserialization - JSON parsing with proper error handling, no unsafe eval
  • SSRF and path traversal - validateProviderUrlForConnectivity() blocks private IPs, localhost, and dangerous ports
  • Cryptographic weaknesses - No custom crypto implementations, standard timeout mechanisms used

Security Controls Verified

Control Status Details
URL Validation ✅ Implemented Blocks private IP ranges, localhost, IPv6 link-local, dangerous ports (22, 3306, 5432, 6379, etc.)
Proxy URL Validation ✅ Implemented isValidProxyUrl() restricts to http/https/socks4/socks5 protocols
Admin Authorization ✅ Implemented Session check with role verification at function entry
Input Sanitization ✅ Implemented URL trimming and protocol validation
Credential Masking ✅ Implemented Regex-based masking for API keys in logs
Timeout Protection ✅ Implemented AbortSignal.timeout(API_TEST_CONFIG.TIMEOUT_MS) prevents hanging requests

📋 OWASP Top 10 Coverage

  • A01: Injection - Clean (no raw queries or command execution)
  • A02: Broken Authentication - Clean (proper session validation)
  • A03: Sensitive Data Exposure - Clean (credentials masked in logs)
  • A04: XML External Entities - N/A (no XML parsing)
  • A05: Broken Access Control - Clean (admin role required)
  • A06: Security Misconfiguration - Clean (no debug flags)
  • A07: XSS - Clean (React auto-escaping)
  • A08: Insecure Deserialization - Clean (safe JSON parsing)
  • A09: Known Vulnerabilities - N/A (no new dependencies)
  • A10: Logging & Monitoring - Clean (proper logging with sensitive data redaction)

🛡️ Security Posture

Strong - The implementation follows secure patterns established in the existing codebase, including proper SSRF prevention, authentication checks, and credential handling.


🤖 Automated security scan by Claude AI - OWASP Top 10 & CWE coverage

Copy link
Owner

@ding113 ding113 left a comment

Choose a reason for hiding this comment

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

📋 Code Review Summary

This PR adds a valuable "Fetch Models" feature that retrieves available models from provider APIs. The implementation covers multiple provider types (OpenAI-compatible, Claude relay, Gemini) with proper authentication handling and error mapping. However, there are several robustness and performance issues that should be addressed before merging.

🔍 Issues Found

  • Critical (🔴): 0 issues
  • High (🟠): 3 issues
  • Medium (🟡): 3 issues
  • Low (🟢): 0 issues

🎯 Priority Actions

  1. Add error handling for JSON parsing - The response.json() call can throw if the provider returns invalid JSON, which would result in a generic error message instead of a helpful one.

  2. Fix type safety in parseModelsResponse - The || operator with type assertion can lead to unexpected behavior when object properties are falsy but not undefined. Use ?? with proper type checking instead.

  3. Memoize sorted model list in ModelMultiSelect - The current implementation sorts on every render with O(n² log n) complexity due to includes() calls inside the sort comparator.

  4. Improve JSON credentials detection - The startsWith("{") check is a weak heuristic. Consider actually parsing and checking for service account fields.

  5. Remove redundant null check - The check for empty models after successful response is redundant since the server action already returns an error for empty results.

💡 General Observations

  • The error handling pattern with errorCode and errorParams is well-designed and consistent with the existing codebase
  • The i18n support is comprehensive with both English and Chinese translations
  • The clearing of allowedModels when provider type changes is a good UX improvement
  • Consider adding rate limiting or debouncing for the fetch button to prevent API abuse

🤖 Automated review by Claude AI - focused on identifying issues for improvement

Copy link
Owner

@ding113 ding113 left a comment

Choose a reason for hiding this comment

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

📋 Code Review Summary

This PR adds a valuable "Fetch Models" feature that retrieves available models from provider APIs. The implementation covers multiple provider types (OpenAI-compatible, Claude relay, Gemini) with proper authentication handling and error mapping. However, there are several robustness and performance issues that should be addressed before merging.

🔍 Issues Found

  • Critical (🔴): 0 issues
  • High (🟠): 3 issues
  • Medium (🟡): 3 issues
  • Low (🟢): 0 issues

🎯 Priority Actions

  1. Add error handling for JSON parsing - The response.json() call can throw if the provider returns invalid JSON, which would result in a generic error message instead of a helpful one.

  2. Fix type safety in parseModelsResponse - The || operator with type assertion can lead to unexpected behavior when object properties are falsy but not undefined. Use ?? with proper type checking instead.

  3. Memoize sorted model list in ModelMultiSelect - The current implementation sorts on every render with O(n² log n) complexity due to includes() calls inside the sort comparator.

  4. Improve JSON credentials detection - The startsWith("{") check is a weak heuristic. Consider actually parsing and checking for service account fields.

  5. Remove redundant null check - The check for empty models after successful response is redundant since the server action already returns an error for empty results.

💡 General Observations

  • The error handling pattern with errorCode and errorParams is well-designed and consistent with the existing codebase
  • The i18n support is comprehensive with both English and Chinese translations
  • The clearing of allowedModels when provider type changes is a good UX improvement
  • Consider adding rate limiting or debouncing for the fetch button to prevent API abuse

🤖 Automated review by Claude AI - focused on identifying issues for improvement

@ding113 ding113 moved this from Backlog to Ready in Claude Code Hub Roadmap Nov 30, 2025
@Kariseven323 Kariseven323 closed this by deleting the head repository Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size/L Large PR (< 1000 lines) size/M Medium PR (< 500 lines)

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

2 participants

Comments