Skip to content

[Audit] Onyx export: review and extend key export rules to improve debug usefulness #90977

@mountiny

Description

@mountiny

Slack thread

Problem

The Onyx state export (Settings → Troubleshoot → Export Onyx state) uses a hand-maintained allow/mask rule table (ONYX_KEY_EXPORT_RULES in src/libs/ExportOnyxState/common.ts) to decide which fields are exported as-is vs. masked.

Only 12 Onyx keys / collection prefixes have explicit rules. The remaining ~100+ keys either:

  • Fall back to a heuristic maskFragileData pass (when the mask toggle is on), or
  • Are exported fully unmasked (when the mask toggle is off)

This means:

  1. Useful debug data is often masked or mangled — when maskFragileData runs on an un-ruled key, numbers are randomized, strings that happen to match keysToMask field names are masked, and structured objects lose their values. Exported files shared with support are frequently not reproducible.
  2. No enforcement — there is nothing to remind engineers to add a rule when a new Onyx key is introduced. The gap silently grows with every new feature.
  3. COLLECTION.REPORT_ACTIONS has no rule — one of the highest-value collections for debugging is processed only by heuristics, not an explicit rule.

Background

The export system has three layers:

  1. ONYX_KEY_EXPORT_RULES — a hand-maintained Record<string, ExportRule> where each entry has an allowList (fields kept as-is) and a maskList (fields length-masked). Any field not on either list is still transformed: numbers randomized, dates replaced, strings masked, objects recursed. Currently covers: SESSION, STASHED_SESSION, CREDENTIALS, STASHED_CREDENTIALS, ACCOUNT, PERSONAL_DETAILS_LIST, COLLECTION.REPORT, COLLECTION.TRANSACTION, COLLECTION.POLICY, USER_WALLET, BANK_ACCOUNT_LIST, CARD_LIST.

  2. onyxKeysToRemove — a hard-coded Set of truly private keys (auth tokens, Onfido IDs, Plaid tokens, all DERIVED keys) that are stripped before any processing.

  3. maskFragileData — a recursive heuristic pass applied to all keys without an export rule (when the mask toggle is on). Uses a keysToMask set of ~35 field names, an amountKeysToRandomize set, and email-regex scanning. This is the fallback for all un-ruled keys.

ONYXKEYS.COLLECTION alone has 50+ prefixes; only 3 have explicit rules. Notable gaps:

  • COLLECTION.REPORT_ACTIONS — message text/HTML only partially caught by maskFragileData
  • COLLECTION.TRANSACTION_VIOLATIONS — useful for debugging, no rule
  • COLLECTION.NEXT_STEP — report next step for debugging approval flows, no rule
  • COLLECTION.REPORT_METADATA — optimistic flags, error state, no rule
  • COLLECTION.POLICY_CATEGORIES, COLLECTION.POLICY_TAGS — workspace config, generally safe, no rule

Goal

Audit all ONYXKEYS (top-level and COLLECTION.*) and for each one explicitly decide:

Category Action
Contains PII / sensitive data Add an entry to ONYX_KEY_EXPORT_RULES with an explicit allowList and maskList
Completely safe to export as-is Add it to ONYX_KEY_EXPORT_RULES with a full allowList
Should never leave the device Add to onyxKeysToRemove

Then add a lint rule or TypeScript-level check so every new ONYXKEYS entry must have a corresponding entry in one of the three buckets — making the coverage self-maintaining going forward.

Acceptance Criteria

  • Every entry in ONYXKEYS (flat keys) and ONYXKEYS.COLLECTION has a deliberate entry in either ONYX_KEY_EXPORT_RULES or onyxKeysToRemove
  • COLLECTION.REPORT_ACTIONS has an explicit export rule covering fields needed to reproduce bugs (action type, timestamp, accountID, pendingAction, errors) with message text/HTML on the mask list
  • A TypeScript compile-time or ESLint check is proposed/added to enforce coverage of new keys
  • Existing maskFragileData heuristic is either retired or kept only as a last-resort fallback for truly unknown structures

Files to Change

  • src/libs/ExportOnyxState/common.ts — primary change target
  • src/ONYXKEYS.ts — reference for all keys
  • Possibly a new ESLint rule or type mapping in src/types/onyx/
Issue OwnerCurrent Issue Owner: @mkhutornyi

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

Status

HIGH

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions