Skip to content

fix(analytics): return false when AnalyticsController state is unreadable#30248

Open
tommasini wants to merge 2 commits into
mainfrom
chore/sentry-fallback-false
Open

fix(analytics): return false when AnalyticsController state is unreadable#30248
tommasini wants to merge 2 commits into
mainfrom
chore/sentry-fallback-false

Conversation

@tommasini
Copy link
Copy Markdown
Contributor

@tommasini tommasini commented May 15, 2026

Description

The hasMetricsConsent function previously fell through to the legacy METRICS_OPT_IN storage key whenever reading from AnalyticsController's persisted state threw an error. This is incorrect because the METRICS_OPT_IN key is never deleted (see migration 108) — meaning a stale AGREED value could cause Sentry traces to be emitted even when the user had already opted out via the newer analytics controller.

By returning false immediately in the catch block, we ensure that Sentry stays disabled whenever the analytics controller state cannot be reliably read, defaulting to the privacy-safe behaviour of treating consent as not given.

Changelog

CHANGELOG entry: Fixed Sentry traces being sent when AnalyticsController state was unreadable

Related issues

Fixes:

Manual testing steps

Feature: Sentry consent fallback behaviour

  Background:
    Given I have MetaMask Mobile installed

  Scenario: AnalyticsController state is unreadable
    Given the AnalyticsController persisted state is corrupted or missing

    When the app starts and evaluates metrics consent
    Then Sentry traces should NOT be sent
    And the app should not fall through to legacy METRICS_OPT_IN storage

  Scenario: AnalyticsController state reports opt-out
    Given the AnalyticsController persisted state is readable
    And optedIn is false

    When the app starts and evaluates metrics consent
    Then Sentry traces should NOT be sent

  Scenario: AnalyticsController state reports opt-in
    Given the AnalyticsController persisted state is readable
    And optedIn is true

    When the app starts and evaluates metrics consent
    Then Sentry traces should be sent normally

Screenshots/Recordings

Before

N/A

After

N/A

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Made with Cursor


Note

Medium Risk
Changes Sentry consent gating behavior when persisted analytics state is unreadable, which could affect whether traces are sent/blocked in some edge cases. Scope is small but touches privacy/telemetry control flow.

Overview
Ensures hasMetricsConsent() fails privacy-safe by returning false if reading/parsing the persisted AnalyticsController state throws, instead of falling back to the legacy METRICS_OPT_IN key.

This prevents stale legacy opt-in values from re-enabling Sentry traces when the newer controller state is corrupted or missing.

Reviewed by Cursor Bugbot for commit 905bbd2. Bugbot is set up for automated code reviews on this repo. Configure here.

…, that means that user had the possibility to opt out and not being opted out in METRICS_OPT_IN storage key value because we never delete it
@tommasini tommasini self-assigned this May 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@github-actions github-actions Bot added the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 15, 2026
@metamaskbotv2 metamaskbotv2 Bot added the team-mobile-platform Mobile Platform team label May 15, 2026
@github-project-automation github-project-automation Bot moved this to Needs dev review in PR review queue May 15, 2026
@tommasini tommasini marked this pull request as ready for review May 15, 2026 13:03
@github-project-automation github-project-automation Bot moved this from Needs dev review to Review finalised - Ready to be merged in PR review queue May 15, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 905bbd2. Configure here.

Comment thread app/util/trace.ts
}
} catch {
// Fall through to legacy storage
return false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catch block omits cachedConsent update unlike other paths

Medium Severity

The catch block returns false but does not set cachedConsent = false, unlike the other two return paths (lines 572 and 583) which both update the cache before returning. This leaves cachedConsent as null, which per line 551's comment means "not yet loaded." Traces will be silently buffered in memory for the entire session rather than being discardable, since the consent state is never recorded as determined. While getCachedConsent() !== true currently treats null and false the same for buffering, the missing cache update is inconsistent with the function's contract in a privacy-critical path.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 905bbd2. Configure here.

@sonarqubecloud
Copy link
Copy Markdown

Comment thread app/util/trace.ts
}
} catch {
// Fall through to legacy storage
return false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return false;
cachedConsent = false;
return false;

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

Labels

pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. size-XS team-mobile-platform Mobile Platform team

Projects

Status: Review finalised - Ready to be merged

Development

Successfully merging this pull request may close these issues.

2 participants