Skip to content

in-automate /api/v2/trackEvent returns 204 for an invalid ma-key, silently discarding events #47

Description

@isaacrowntree

Summary

POST https://in-automate.brevo.com/api/v2/trackEvent returns 204 No Content when the ma-key header contains a value that is not a valid key. It validates the request body synchronously but not the credential, so a caller with a wrong, rotated or malformed key gets an unbroken stream of success responses while nothing is recorded.

Reproduction

# garbage key — accepted
$ curl -o /dev/null -w "%{http_code}\n" -X POST https://in-automate.brevo.com/api/v2/trackEvent \
    -H "ma-key: not-a-real-key-at-all" -H "content-type: application/json" \
    -d '{"email":"someone@example.com","event":"probe"}'
204

# missing header — correctly rejected
$ curl -X POST https://in-automate.brevo.com/api/v2/trackEvent \
    -H "ma-key: " -H "content-type: application/json" \
    -d '{"email":"someone@example.com","event":"probe"}'
401 {"code":"unauthorized","message":"'ma-key' is missing in headers"}

# body IS validated synchronously
$ ... -d '{"event":"probe"}'
400 {"code":"request","message":"email is empty or invalid"}

$ ... -d '{"email":"someone@example.com"}'
400 {"code":"request","message":"event is empty"}

So the endpoint checks that the header is present, and checks the body, but does not check that the key is valid before returning 204.

Why this is worse than a normal auth bug

A 401 is self-announcing — you find out immediately. A 204 is indistinguishable from success, so the failure mode is:

  • an integration ships with a bad or stale key,
  • every call returns 204 and every log line looks healthy,
  • automations never fire, and
  • nobody notices until a customer asks why their birthday or win-back emails stopped.

It also makes the endpoint untestable from the outside. There is no way for an integrator to verify their key works short of building an automation in the UI and watching whether a contact enters it — the HTTP response carries no signal at all.

What would resolve it

Return 401 when ma-key is present but invalid, matching the existing behaviour for a missing header. If asynchronous processing means validity genuinely cannot be determined at request time, then a 202 Accepted would at least be honest about not being a confirmation — but a synchronous key check would be far more useful, since the key is a static credential and does not require the event pipeline to resolve.

Context

Found while evaluating whether an OAuth access token can stand in for an ma-key, since /v3/events rejects OAuth tokens outright (filed separately as #46). The 204 initially looked like a positive result; it was only the control test with a deliberately invalid key that showed the response means nothing either way.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions