避免IM传输错误泄露签名

This commit is contained in:
zhx 2026-07-13 23:32:44 +08:00
parent 255d2b8fc8
commit fca2cbb39f
2 changed files with 29 additions and 1 deletions

View File

@ -464,7 +464,14 @@ func (c *RESTClient) post(ctx context.Context, command string, payload any, out
response, err := c.httpClient.Do(request) response, err := c.httpClient.Do(request)
if err != nil { if err != nil {
return err var transportErr *url.Error
if errors.As(err, &transportErr) {
// net/http 的 url.Error.Error 会拼入完整请求 URL而腾讯 IM UserSig 位于
// query string。只向上保留底层网络原因既维持 errors.Is 的超时/取消
// 语义,又避免日志和 notice last_error 持久化可用签名。
return fmt.Errorf("tencent im request failed: %w", transportErr.Err)
}
return fmt.Errorf("tencent im request failed: %w", err)
} }
defer response.Body.Close() defer response.Body.Close()

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"errors"
"io" "io"
"net/http" "net/http"
"strings" "strings"
@ -345,6 +346,26 @@ func TestRESTClientKickUserBuildsTencentRequest(t *testing.T) {
} }
} }
func TestRESTClientTransportErrorDoesNotExposeUserSig(t *testing.T) {
client := newTestRESTClient(t, func(request *http.Request) (*http.Response, error) {
if request.URL.Query().Get("usersig") == "" {
t.Fatal("test request must contain the signed Tencent IM query")
}
return nil, errors.New("synthetic EOF")
})
err := client.KickUser(context.Background(), 10002)
if err == nil {
t.Fatal("expected transport failure")
}
if strings.Contains(err.Error(), "usersig=") || strings.Contains(err.Error(), "sdkappid=") {
t.Fatalf("transport error exposed signed request URL: %q", err.Error())
}
if !strings.Contains(err.Error(), "synthetic EOF") {
t.Fatalf("transport cause must remain actionable: %q", err.Error())
}
}
func newTestRESTClient(t *testing.T, roundTrip roundTripFunc) *RESTClient { func newTestRESTClient(t *testing.T, roundTrip roundTripFunc) *RESTClient {
t.Helper() t.Helper()