From 48396d3f33948e8b8e7d0475b9d03cb02a15e50a Mon Sep 17 00:00:00 2001 From: Deadwalk Date: Sun, 28 Sep 2025 16:41:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DCodeReview=E5=8F=91?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E5=AE=89=E5=85=A8=E9=97=AE=E9=A2=98=E5=92=8C?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B4=A8=E9=87=8F=E9=97=AE=E9=A2=98=20|=20fi?= =?UTF-8?q?x=20security=20and=20code=20quality=20issues=20identified=20by?= =?UTF-8?q?=20CodeReview?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复JSON注入漏洞:使用json.Marshal()安全转义字符串内容 - 定义常量CHARS_PER_TOKEN替换硬编码的token估算数字4 - 处理UnmarshalJSON错误,避免静默失败并记录错误日志 - 定义常量替换硬编码的API端点路径,提高可维护性 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- relay/adaptor/anthropic/adaptor.go | 11 +++++++++-- relay/adaptor/anthropic/main.go | 12 +++++++++--- relay/controller/anthropic.go | 10 ++++++++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/relay/adaptor/anthropic/adaptor.go b/relay/adaptor/anthropic/adaptor.go index 44803de4..8dbb20c0 100644 --- a/relay/adaptor/anthropic/adaptor.go +++ b/relay/adaptor/anthropic/adaptor.go @@ -14,6 +14,13 @@ import ( "github.com/songquanpeng/one-api/relay/relaymode" ) +const ( + // NativeAnthropicEndpoint is the endpoint for native Anthropic API + NativeAnthropicEndpoint = "/v1/messages" + // ThirdPartyAnthropicEndpoint is the endpoint for third-party providers supporting Anthropic protocol + ThirdPartyAnthropicEndpoint = "/anthropic/v1/messages" +) + type Adaptor struct { } @@ -24,13 +31,13 @@ func (a *Adaptor) Init(meta *meta.Meta) { func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { // For native Anthropic API if strings.Contains(meta.BaseURL, "api.anthropic.com") { - return fmt.Sprintf("%s/v1/messages", meta.BaseURL), nil + return fmt.Sprintf("%s%s", meta.BaseURL, NativeAnthropicEndpoint), nil } // For third-party providers supporting Anthropic protocol (like DeepSeek) // They typically expose the endpoint at /anthropic/v1/messages baseURL := strings.TrimSuffix(meta.BaseURL, "/") - return fmt.Sprintf("%s/anthropic/v1/messages", baseURL), nil + return fmt.Sprintf("%s%s", baseURL, ThirdPartyAnthropicEndpoint), nil } func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request, meta *meta.Meta) error { diff --git a/relay/adaptor/anthropic/main.go b/relay/adaptor/anthropic/main.go index b0d721bb..a52d97d5 100644 --- a/relay/adaptor/anthropic/main.go +++ b/relay/adaptor/anthropic/main.go @@ -93,9 +93,15 @@ func ConvertRequest(textRequest model.GeneralOpenAIRequest) *Request { if message.Role == "system" && claudeRequest.System.IsEmpty() { // Create a SystemPrompt from the string content systemPrompt := SystemPrompt{} - systemData := []byte(`"` + message.StringContent() + `"`) // Wrap in JSON string quotes - _ = systemPrompt.UnmarshalJSON(systemData) - claudeRequest.System = systemPrompt + systemData, err := json.Marshal(message.StringContent()) // Safely escape string for JSON + if err != nil { + logger.SysError(fmt.Sprintf("Failed to marshal system prompt: %v", err)) + } else { + if err := systemPrompt.UnmarshalJSON(systemData); err != nil { + logger.SysError(fmt.Sprintf("Failed to unmarshal system prompt: %v", err)) + } + claudeRequest.System = systemPrompt + } continue } claudeMessage := Message{ diff --git a/relay/controller/anthropic.go b/relay/controller/anthropic.go index a0c512bc..641eb0f2 100644 --- a/relay/controller/anthropic.go +++ b/relay/controller/anthropic.go @@ -142,6 +142,12 @@ func getAnthropicRequestBody(c *gin.Context, anthropicRequest *anthropic.Request return bytes.NewBuffer(jsonData), nil } +const ( + // CHARS_PER_TOKEN represents the rough character-to-token ratio for Anthropic models + // This is a conservative estimate: approximately 1 token per 4 characters + CHARS_PER_TOKEN = 4 +) + func estimateAnthropicTokens(request *anthropic.Request) int { // Simple token estimation for Anthropic requests // This is a rough estimation, actual implementation might need more sophisticated logic @@ -150,14 +156,14 @@ func estimateAnthropicTokens(request *anthropic.Request) int { // Count tokens in system prompt if !request.System.IsEmpty() { systemText := request.System.String() - totalTokens += len(systemText) / 4 // rough estimate: 1 token per 4 characters + totalTokens += len(systemText) / CHARS_PER_TOKEN // rough estimate: 1 token per 4 characters } // Count tokens in messages for _, message := range request.Messages { for _, content := range message.Content { if content.Type == "text" { - totalTokens += len(content.Text) / 4 + totalTokens += len(content.Text) / CHARS_PER_TOKEN } } }