fix: expose param override audits for sensitive message fields (#4974)

This commit is contained in:
Seefs
2026-05-19 18:28:03 +08:00
committed by GitHub
parent 146dd77b83
commit 0d4b25795a
3 changed files with 114 additions and 13 deletions
+90
View File
@@ -12,6 +12,7 @@ import (
"github.com/QuantumNous/new-api/dto"
"github.com/QuantumNous/new-api/setting/model_setting"
"github.com/samber/lo"
"github.com/stretchr/testify/require"
)
func TestApplyParamOverrideTrimPrefix(t *testing.T) {
@@ -2184,6 +2185,95 @@ func TestApplyParamOverrideWithRelayInfoRecordsOnlyKeyOperationsWhenDebugDisable
}
}
func TestApplyParamOverrideWithRelayInfoRecordsConversationBodyOperationsWhenDebugDisabled(t *testing.T) {
originalDebugEnabled := common2.DebugEnabled
common2.DebugEnabled = false
t.Cleanup(func() {
common2.DebugEnabled = originalDebugEnabled
})
info := &RelayInfo{
ChannelMeta: &ChannelMeta{
ParamOverride: map[string]interface{}{
"operations": []interface{}{
map[string]interface{}{
"mode": "replace",
"path": "messages.0.content",
"from": "hello",
"to": "hi",
},
map[string]interface{}{
"mode": "set",
"path": "input.0.content.0.text",
"value": "rewritten response input",
},
map[string]interface{}{
"mode": "set",
"path": "instructions",
"value": "new instruction",
},
map[string]interface{}{
"mode": "append",
"path": "contents.0.parts",
"value": map[string]interface{}{"text": "new gemini part"},
},
map[string]interface{}{
"mode": "copy",
"from": "system",
"to": "metadata.system_copy",
},
map[string]interface{}{
"mode": "set",
"path": "temperature",
"value": 0.1,
},
},
},
},
}
out, err := ApplyParamOverrideWithRelayInfo([]byte(`{
"messages":[{"role":"user","content":"hello world"}],
"input":[{"role":"user","content":[{"type":"input_text","text":"original response input"}]}],
"instructions":"old instruction",
"system":"old system",
"contents":[{"role":"user","parts":[{"text":"hello gemini"}]}],
"temperature":0.7
}`), info)
require.NoError(t, err)
assertJSONEqual(t, `{
"messages":[{"role":"user","content":"hi world"}],
"input":[{"role":"user","content":[{"type":"input_text","text":"rewritten response input"}]}],
"instructions":"new instruction",
"system":"old system",
"contents":[{"role":"user","parts":[{"text":"hello gemini"},{"text":"new gemini part"}]}],
"temperature":0.1,
"metadata":{"system_copy":"old system"}
}`, string(out))
require.Equal(t, []string{
"replace messages.0.content from hello to hi",
"set input.0.content.0.text = rewritten response input",
"set instructions = new instruction",
"append contents.0.parts with {\"text\":\"new gemini part\"}",
"copy system -> metadata.system_copy",
}, info.ParamOverrideAudit)
}
func TestShouldAuditParamPathUsesFieldBoundaryPrefixMatching(t *testing.T) {
originalDebugEnabled := common2.DebugEnabled
common2.DebugEnabled = false
t.Cleanup(func() {
common2.DebugEnabled = originalDebugEnabled
})
require.True(t, shouldAuditParamPath("messages"))
require.True(t, shouldAuditParamPath("messages.0.content"))
require.True(t, shouldAuditParamPath("systemInstruction.parts.0.text"))
require.False(t, shouldAuditParamPath("model_name"))
require.False(t, shouldAuditParamPath("message"))
}
func assertJSONEqual(t *testing.T, want, got string) {
t.Helper()