Skip to content

before_send event modifications leak to the scope #1551

@jpnurmi

Description

@jpnurmi

Description

When before_send modifies values on an event, the changes can leak back into the scope.

  • user and fingerprint are placed into the event by reference (PLACE_VALUE) rather than being cloned, so any modification corrupts the scope directly.
  • tags, extra, and contexts use PLACE_CLONED_VALUE, but sentry__value_clone() only performs a shallow clone so modifying a nested object still mutates the scope's original.

When does the problem happen

  • During build
  • During run-time
  • When capturing a hard crash

Steps To Reproduce

#include <stdio.h>
#include <sentry.h>

sentry_value_t before_send(sentry_value_t event, void *hint, void *user_data)
{
    sentry_value_t user = sentry_value_get_by_key(event, "user");
    char* original = sentry_value_to_json(user);

    sentry_value_set_by_key(user, "email", sentry_value_new_string("redacted"));
    char* redacted = sentry_value_to_json(user);

    fprintf(stderr, "%s ==> %s\n", original, redacted);
    sentry_free(original);
    sentry_free(redacted);

    return event;
}

int main(int argc, char *argv[])
{
    sentry_options_t *options = sentry_options_new();
    sentry_options_set_dsn(options, SENTRY_DSN);
    sentry_options_set_before_send(options, before_send, nullptr);
    sentry_init(options);

    sentry_set_user(sentry_value_new_user(NULL, "somebody", "somebody@example.com", NULL));

    sentry_capture_event(sentry_value_new_event()); // {"username":"somebody","email":"somebody@example.com"} ==> {"username":"somebody","email":"redacted"}
    sentry_capture_event(sentry_value_new_event()); // {"username":"somebody","email":"redacted"} ==> {"username":"somebody","email":"redacted"}

    sentry_close();
}

Log output

Expected output:

{"username":"somebody","email":"somebody@example.com"} ==> {"username":"somebody","email":"redacted"}
{"username":"somebody","email":"somebody@example.com"} ==> {"username":"somebody","email":"redacted"}

Actual output:

{"username":"somebody","email":"somebody@example.com"} ==> {"username":"somebody","email":"redacted"}
{"username":"somebody","email":"redacted"} ==> {"username":"somebody","email":"redacted"}

The second before_send receives "redacted" as the original email because the first before_send mutated the scope's user object in place.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bugsomething isn't working as it shouldErrorsissues relates to the error reporting productNativeplatform label
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions