knadh/listmonk · error
invalid azure event grid shared secret
Error message
invalid azure event grid shared secret
What it means
verifyAuth compares the configured shared secret against the value supplied in the webhook request — either the query parameter (querySecretParam) or the configured header. This error is returned when neither location carries a value equal to the configured shared secret, so the Azure Event Grid delivery is rejected as unauthenticated.
Source
Thrown at internal/bounce/webhooks/azure.go:170
if req == nil {
return errors.New("missing azure event grid request context")
}
querySecret := strings.TrimSpace(req.URL.Query().Get(querySecretParam))
if secretsEqual(a.sharedSecret, querySecret) {
return nil
}
headerName := a.sharedSecretHeader
if headerName == "" {
headerName = defaultSecretHeader
}
headerSecret := strings.TrimSpace(req.Header.Get(headerName))
if secretsEqual(a.sharedSecret, headerSecret) {
return nil
}
return errors.New("invalid azure event grid shared secret")
}
func secretsEqual(expected, given string) bool {
if expected == "" || given == "" {
return false
}
return subtle.ConstantTimeCompare([]byte(expected), []byte(given)) == 1
}
func parseAzureEvents(b []byte) ([]azureEvent, error) {
var raws []json.RawMessage
if err := json.Unmarshal(b, &raws); err != nil {
return nil, fmt.Errorf("error unmarshalling azure notification array: %v", err)
}
events := make([]azureEvent, 0, len(raws))
for _, raw := range raws {
ev := azureEvent{RawData: raw}View on GitHub (pinned to 670c01717d)
Solutions
- Re-register the Event Grid subscription with the secret appended, e.g. https://host/webhooks/azure?secret=<sharedSecret>, or configure the matching header on delivery.
- Verify the configured shared secret in the app matches the one embedded in the Event Grid subscription URL/header; rotate both together.
- Check that any reverse proxy or WAF in front of the app forwards the query parameter and custom header intact.
- If this error appears from unknown scanners, it is working as intended — consider rate-limiting/blocking the source IP.
Example fix
// before az bg create --topic ... --endpoint https://host/webhooks/azure // after az bg create --topic ... --endpoint "https://host/webhooks/azure?secret=YOUR_SHARED_SECRET"
Defensive patterns
Strategy: try-catch
Validate before calling
u, _ := url.Parse(webhookURL)
if u.Query().Get("secret") == "" {
// subscription URL lacks the shared secret; fix before registering with Event Grid
} Type guard
func azureWebhookURLHasSecret(raw string) bool {
u, err := url.Parse(raw)
return err == nil && strings.TrimSpace(u.Query().Get("secret")) != ""
} Try / catch
bounces, err := azure.ProcessBounce(body, req)
if err != nil {
if strings.Contains(err.Error(), "invalid azure event grid shared secret") {
// return 401; alert if the source IP is not an Azure datacenter
return echo.NewHTTPError(http.StatusUnauthorized)
}
return err
} Prevention
- Embed the secret in the webhook URL query (or header) when creating the Event Grid subscription.
- Rotate the secret in the app and re-register the subscription together.
- Ensure reverse proxies forward query params and custom headers unchanged.
- Monitor this error for scanner traffic and rate-limit offenders.
When it happens
Trigger: A POST arrives at the Azure webhook while a shared secret is configured, but the request carries no secret or a wrong secret in both the expected query parameter and header.
Common situations: The Azure Event Grid subscription was created without appending the secret to the webhook URL query string; the secret was rotated in the app config but the subscription still uses the old URL; a proxy strips custom headers or the query string; the endpoint is being probed by unauthorized traffic.
Related errors
- missing azure event grid request context
- empty event payload
- missing event data
- missing validationCode in subscription payload
- error reading validation data: %v
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/7cf3d1972254b5b0.
Report an issue: GitHub.