fix(edge): Gemini provider 도구 ID를 검증한다

This commit is contained in:
toki 2026-08-15 10:56:07 +09:00
parent 48b69740df
commit 00761ba0c8
2 changed files with 29 additions and 0 deletions

View file

@ -15,6 +15,7 @@ const (
defaultLogicalRequestTTL = 30 * time.Minute
defaultLogicalRequestFrontierCapacity = 64
defaultLogicalRequestMappingCapacity = 512
maxOpaqueProviderToolIDLength = 16 * 1024
)
var (
@ -585,6 +586,17 @@ func validateLogicalRequestContinuationLineage(prefix logicalRequestLineage, exp
}
func validLogicalRequestID(value string) bool {
if strings.HasPrefix(value, geminiThoughtSignatureToolIDPrefix) {
if len(value) > maxOpaqueProviderToolIDLength {
return false
}
decodedID, _, encoded, err := decodeGeminiThoughtSignatureToolID(value)
return err == nil && encoded && validPlainLogicalRequestID(decodedID)
}
return validPlainLogicalRequestID(value)
}
func validPlainLogicalRequestID(value string) bool {
if value == "" || len(value) > 256 {
return false
}

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
"testing"
"time"
@ -1120,6 +1121,22 @@ func TestLogicalRequestExpiredStateIsRejected(t *testing.T) {
}
}
func TestValidLogicalRequestIDAcceptsBoundedGeminiSignatureEnvelope(t *testing.T) {
encoded := encodeGeminiThoughtSignatureToolID("provider_call", strings.Repeat("signature", 128))
if len(encoded) <= 256 {
t.Fatalf("fixture is not larger than the plain id limit: %d", len(encoded))
}
if !validLogicalRequestID(encoded) {
t.Fatal("bounded Gemini signature envelope was rejected")
}
if validLogicalRequestID(geminiThoughtSignatureToolIDPrefix + "not-base64!") {
t.Fatal("malformed Gemini signature envelope was accepted")
}
if validLogicalRequestID(encodeGeminiThoughtSignatureToolID("provider_call", strings.Repeat("x", maxOpaqueProviderToolIDLength))) {
t.Fatal("oversized Gemini signature envelope was accepted")
}
}
func mustChatLogicalRequestLineage(t *testing.T, content string, tools ...any) logicalRequestLineage {
t.Helper()
raw, err := json.Marshal(chatCompletionRequest{