From 69b9677baeac77771a03eb533cc3fd7d9db04dbc Mon Sep 17 00:00:00 2001 From: Jan Komarek Date: Tue, 4 Feb 2025 13:57:03 +0100 Subject: [PATCH] feat(suite, suite-common): report firmware version check fail to Sentry --- .../actions/settings/deviceSettingsActions.ts | 12 +++------ .../useReportDeviceCompromised.ts | 2 +- .../src/middlewares/suite/eventsMiddleware.ts | 12 ++++++++- .../suite/src/support/extraDependencies.ts | 2 ++ suite-common/firmware/src/firmwareThunks.ts | 26 ++++++++++++++++--- .../redux-utils/src/extraDependenciesType.ts | 5 ++++ .../test-utils/src/extraDependenciesMock.ts | 2 ++ 7 files changed, 48 insertions(+), 13 deletions(-) diff --git a/packages/suite/src/actions/settings/deviceSettingsActions.ts b/packages/suite/src/actions/settings/deviceSettingsActions.ts index 29fef7b5034..4136827642a 100644 --- a/packages/suite/src/actions/settings/deviceSettingsActions.ts +++ b/packages/suite/src/actions/settings/deviceSettingsActions.ts @@ -179,15 +179,11 @@ export const resetDevice = if (!result.success) { dispatch(notificationsActions.addToast({ type: 'error', error: result.payload.error })); if (result.payload.code === 'Failure_EntropyCheck') { - const model = device?.features?.internal_model; - const revision = device?.features?.revision; - const version = getFirmwareVersion(device); - const vendor = device?.features?.fw_vendor; reportCheckFail('Entropy', { - model, - revision, - version, - vendor, + model: device?.features?.internal_model, + revision: device?.features?.revision, + version: getFirmwareVersion(device), + vendor: device?.features?.fw_vendor, error: result.payload.error, }); const hardErrors: string[] = [ diff --git a/packages/suite/src/components/suite/SecurityCheck/useReportDeviceCompromised.ts b/packages/suite/src/components/suite/SecurityCheck/useReportDeviceCompromised.ts index 65136105c4f..f4f0a912ebf 100644 --- a/packages/suite/src/components/suite/SecurityCheck/useReportDeviceCompromised.ts +++ b/packages/suite/src/components/suite/SecurityCheck/useReportDeviceCompromised.ts @@ -11,7 +11,7 @@ import { selectFirmwareRevisionCheckError } from 'src/reducers/suite/suiteReduce import { captureSentryMessage, withSentryScope } from 'src/utils/suite/sentry'; export const reportCheckFail = ( - checkType: 'Firmware revision' | 'Firmware hash' | 'Entropy', + checkType: 'Entropy' | 'Firmware hash' | 'Firmware revision' | 'Firmware version', contextData: Record, errorPayload?: unknown, ) => { diff --git a/packages/suite/src/middlewares/suite/eventsMiddleware.ts b/packages/suite/src/middlewares/suite/eventsMiddleware.ts index bb09cb2c791..f8e6ae92c7f 100644 --- a/packages/suite/src/middlewares/suite/eventsMiddleware.ts +++ b/packages/suite/src/middlewares/suite/eventsMiddleware.ts @@ -16,6 +16,7 @@ import { import { DEVICE } from '@trezor/connect'; import { SUITE } from 'src/actions/suite/constants'; +import { reportCheckFail } from 'src/components/suite/SecurityCheck/useReportDeviceCompromised'; import { Action, AppState, Dispatch } from 'src/types/suite'; /* @@ -68,7 +69,16 @@ const eventsMiddleware = } if (action.type === DEVICE.FIRMWARE_VERSION_CHANGED) { - // TODO: show warning? move this to different middleware? + // TODO: Add UI. + const { device, oldVersion, newVersion } = action.payload; + reportCheckFail('Firmware version', { + model: device?.features?.internal_model, + revision: device?.features?.revision, + oldVersion, + newVersion, + vendor: device?.features?.fw_vendor, + error: 'Firmware version changed unexpectedly.', + }); } if (deviceActions.selectDevice.match(action)) { diff --git a/packages/suite/src/support/extraDependencies.ts b/packages/suite/src/support/extraDependencies.ts index cf3553bc5b4..d642a12cb02 100644 --- a/packages/suite/src/support/extraDependencies.ts +++ b/packages/suite/src/support/extraDependencies.ts @@ -32,6 +32,7 @@ import { findLabelsToBeMovedOrDeleted, moveLabelsForRbfAction, } from 'src/actions/wallet/moveLabelsForRbfActions'; +import { reportCheckFail } from 'src/components/suite/SecurityCheck/useReportDeviceCompromised'; import { selectIsWindowVisible } from 'src/reducers/suite/windowReducer'; import { fixLoadedCoinjoinAccount } from 'src/utils/wallet/coinjoinUtils'; @@ -216,5 +217,6 @@ export const extraDependencies: ExtraDependencies = { utils: { saveAs: (data, fileName) => saveAs(data, fileName), connectInitSettings, + reportCheckFail, }, }; diff --git a/suite-common/firmware/src/firmwareThunks.ts b/suite-common/firmware/src/firmwareThunks.ts index 416e8835e19..0c495694765 100644 --- a/suite-common/firmware/src/firmwareThunks.ts +++ b/suite-common/firmware/src/firmwareThunks.ts @@ -79,6 +79,7 @@ export const firmwareUpdate = createThunk< const { selectors: { selectLanguage }, + utils: { reportCheckFail }, } = extra; const device = selectSelectedDevice(getState()); @@ -154,7 +155,14 @@ export const firmwareUpdate = createThunk< connectResponse: firmwareUpdateResponse, }); } else { - const { check, versionCheck } = firmwareUpdateResponse.payload; + const { + check, + versionCheck, + bootloaderVersion, + binaryVersion, + installedVersion, + releaseVersion, + } = firmwareUpdateResponse.payload; if (check === 'mismatch') { // hash check was performed, and it does not match, so consider firmware counterfeit dispatch(handleFwHashMismatch(device)); @@ -165,12 +173,24 @@ export const firmwareUpdate = createThunk< errorMessage: firmwareUpdateResponse.payload.checkError, }), ); - } else if (!binary && !versionCheck) { - // TODO: log to sentry } else { dispatch(handleFwHashValid(device)); } + // TODO: Add to the if-else block above and add handle in UI. + if (!binary && !versionCheck) { + reportCheckFail('Firmware version', { + model: device.features?.internal_model, + revision: device.features?.revision, + vendor: device.features?.fw_vendor, + bootloaderVersion, + binaryVersion, + installedVersion, + releaseVersion, + error: 'Unexpected firmware version change during firmware update.', + }); + } + return fulfillWithValue({ device, ...targetProperties, diff --git a/suite-common/redux-utils/src/extraDependenciesType.ts b/suite-common/redux-utils/src/extraDependenciesType.ts index 60120c5c137..f8877e1b0bd 100644 --- a/suite-common/redux-utils/src/extraDependenciesType.ts +++ b/suite-common/redux-utils/src/extraDependenciesType.ts @@ -138,6 +138,11 @@ export type ExtraDependencies = { utils: { saveAs: (data: Blob, fileName: string) => void; connectInitSettings: ConnectInitSettings; + reportCheckFail: ( + checkType: 'Entropy' | 'Firmware hash' | 'Firmware revision' | 'Firmware version', + contextData: Record, + errorPayload?: unknown, + ) => void; }; }; diff --git a/suite-common/test-utils/src/extraDependenciesMock.ts b/suite-common/test-utils/src/extraDependenciesMock.ts index 4500b519174..0548089b67c 100644 --- a/suite-common/test-utils/src/extraDependenciesMock.ts +++ b/suite-common/test-utils/src/extraDependenciesMock.ts @@ -146,5 +146,7 @@ export const extraDependenciesMock: ExtraDependencies = { appUrl: '@suite-native/app', }, }, + reportCheckFail: (checkType, _contextData) => + console.warn(`Reporting ${checkType} check fail. Implementation on phone not ready.`), }, };