Follow-up to #6013. The signing path silently fell back to using the raw secret string as the HMAC key when a whsec_-prefixed secret had invalid base64, producing signatures no receiver could verify with no server-side signal. - Extract resolveSigningKey helper that errors on invalid whsec_ base64 - Post returns that error (logged by the async dispatcher); ValidateSigningSecret rejects it at write time so a bad secret is never stored - Fix stale comment referencing a nonexistent Authorization header - Add Go tests: key derivation, secret validation, end-to-end signature round-trip, and the invariant that the secret never leaks into API responses
29 lines
1 KiB
Go
29 lines
1 KiB
Go
package v1
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
storepb "github.com/usememos/memos/proto/gen/store"
|
|
"github.com/usememos/memos/store"
|
|
)
|
|
|
|
// TestConvertUserWebhookFromUserSettingOmitsSigningSecret guards the core security
|
|
// invariant of the signing-secret feature: the secret is INPUT_ONLY and must never
|
|
// be copied into an API response, even though it is persisted in the user setting.
|
|
func TestConvertUserWebhookFromUserSettingOmitsSigningSecret(t *testing.T) {
|
|
user := &store.User{Username: "alice"}
|
|
stored := &storepb.WebhooksUserSetting_Webhook{
|
|
Id: "webhook-id",
|
|
Title: "My Webhook",
|
|
Url: "https://example.com/postreceive",
|
|
SigningSecret: "whsec_super-secret-value",
|
|
}
|
|
|
|
apiWebhook := convertUserWebhookFromUserSetting(stored, user)
|
|
|
|
require.Equal(t, "My Webhook", apiWebhook.DisplayName)
|
|
require.Equal(t, "https://example.com/postreceive", apiWebhook.Url)
|
|
require.Empty(t, apiWebhook.SigningSecret, "signing secret must never be returned in API responses")
|
|
}
|