Skip to content

Commit

Permalink
Merge branch 'develop' into fix-account-pinning-20918
Browse files Browse the repository at this point in the history
  • Loading branch information
NidhiKJha committed Dec 13, 2023
2 parents 3447a2b + 2023178 commit b9cfbc9
Show file tree
Hide file tree
Showing 30 changed files with 1,027 additions and 780 deletions.
5 changes: 4 additions & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ npmAuditIgnoreAdvisories:
# Issue: protobufjs Prototype Pollution vulnerability
# URL - https://github.com/advisories/GHSA-h755-8qp9-cq85
# Not easily patched. Minimally effects the extension due to usage of
# LavaMoat lockdown.
# LavaMoat lockdown. Additional id added that resolves to the same advisory
# but has a different entry due to it being a new dependency of
# @trezor/connect-web. Upgrading
- 1092429
- 1095136

# Issue: Regular Expression Denial of Service (ReDOS)
# URL: https://github.com/advisories/GHSA-257v-vj4p-3w2h
Expand Down
2 changes: 1 addition & 1 deletion app/manifest/v3/chrome.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'; frame-ancestors 'none';"
"extension_pages": "script-src 'self'; object-src 'self'; frame-ancestors 'self';"
},
"externally_connectable": {
"matches": ["https://metamask.io/*"],
Expand Down
7 changes: 6 additions & 1 deletion app/scripts/controllers/app-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ export default class AppStateController extends EventEmitter {
}

_requestApproval() {
// If we already have a pending request this is a no-op
if (this._approvalRequestId) {
return;
}
this._approvalRequestId = uuid();

this.messagingSystem
Expand All @@ -455,7 +459,8 @@ export default class AppStateController extends EventEmitter {
true,
)
.catch(() => {
// Intentionally ignored as promise not currently used
// If the promise fails, we allow a new popup to be triggered
this._approvalRequestId = null;
});
}

Expand Down
136 changes: 136 additions & 0 deletions app/scripts/lib/offscreen-bridge/trezor-offscreen-bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { TrezorBridge } from '@metamask/eth-trezor-keyring';
import type {
EthereumSignMessage,
EthereumSignTransaction,
Params,
EthereumSignTypedDataTypes,
ConnectSettings,
Manifest,
Response as TrezorResponse,
EthereumSignedTx,
PROTO,
EthereumSignTypedHash,
} from '@trezor/connect-web';
import {
OffscreenCommunicationEvents,
OffscreenCommunicationTarget,
TrezorAction,
} from '../../../../shared/constants/offscreen-communication';

/**
* This class is used as a custom bridge for the Trezor connection. Every
* hardware wallet keyring also requires a bridge that has a known interface
* that the keyring can call into for specific functions. The bridge then makes
* whatever calls or requests it needs to in order to fulfill the request from
* the keyring. In this case, the bridge is used to communicate with the
* Offscreen Document. Inside the Offscreen document the trezor-iframe is
* embedded that will listen for these calls and communicate with the
* trezor/connect-web library.
*/
export class TrezorOffscreenBridge implements TrezorBridge {
model: string | undefined;

init(
settings: {
manifest: Manifest;
} & Partial<ConnectSettings>,
) {
chrome.runtime.onMessage.addListener((msg) => {
if (
msg.target === OffscreenCommunicationTarget.extension &&
msg.event === OffscreenCommunicationEvents.trezorDeviceConnect
) {
this.model = msg.payload;
}
});

return new Promise<void>((resolve) => {
chrome.runtime.sendMessage(
{
target: OffscreenCommunicationTarget.trezorOffscreen,
action: TrezorAction.init,
params: settings,
},
() => {
resolve();
},
);
});
}

dispose() {
return new Promise<void>((resolve) => {
chrome.runtime.sendMessage(
{
target: OffscreenCommunicationTarget.trezorOffscreen,
action: TrezorAction.dispose,
},
() => {
resolve();
},
);
});
}

getPublicKey(params: { path: string; coin: string }) {
return new Promise((resolve) => {
chrome.runtime.sendMessage(
{
target: OffscreenCommunicationTarget.trezorOffscreen,
action: TrezorAction.getPublicKey,
params,
},
(response) => {
resolve(response);
},
);
}) as TrezorResponse<{ publicKey: string; chainCode: string }>;
}

ethereumSignTransaction(params: Params<EthereumSignTransaction>) {
return new Promise((resolve) => {
chrome.runtime.sendMessage(
{
target: OffscreenCommunicationTarget.trezorOffscreen,
action: TrezorAction.signTransaction,
params,
},
(response) => {
resolve(response);
},
);
}) as TrezorResponse<EthereumSignedTx>;
}

ethereumSignMessage(params: Params<EthereumSignMessage>) {
return new Promise((resolve) => {
chrome.runtime.sendMessage(
{
target: OffscreenCommunicationTarget.trezorOffscreen,
action: TrezorAction.signMessage,
params,
},
(response) => {
resolve(response);
},
);
}) as TrezorResponse<PROTO.MessageSignature>;
}

ethereumSignTypedData<T extends EthereumSignTypedDataTypes>(
params: Params<EthereumSignTypedHash<T>>,
) {
return new Promise((resolve) => {
chrome.runtime.sendMessage(
{
target: OffscreenCommunicationTarget.trezorOffscreen,
action: TrezorAction.signTypedData,
params,
},
(response) => {
resolve(response);
},
);
}) as TrezorResponse<PROTO.EthereumTypedDataSignature>;
}
}
6 changes: 6 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ import { securityProviderCheck } from './lib/security-provider-helpers';
import { IndexedDBPPOMStorage } from './lib/ppom/indexed-db-backend';
///: END:ONLY_INCLUDE_IF
import { updateCurrentLocale } from './translate';
import { TrezorOffscreenBridge } from './lib/offscreen-bridge/trezor-offscreen-bridge';
///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
import { snapKeyringBuilder, getAccountsBySnapId } from './lib/snap-keyring';
///: END:ONLY_INCLUDE_IF
Expand Down Expand Up @@ -958,6 +959,10 @@ export default class MetamaskController extends EventEmitter {
);
}
///: END:ONLY_INCLUDE_IF
} else if (isManifestV3) {
additionalKeyrings.push(
hardwareKeyringBuilderFactory(TrezorKeyring, TrezorOffscreenBridge),
);
}

///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
Expand Down Expand Up @@ -3776,6 +3781,7 @@ export default class MetamaskController extends EventEmitter {
const keyringOverrides = this.opts.overrides?.keyrings;
let keyringName = null;
if (
deviceName !== HardwareDeviceNames.trezor &&
deviceName !== HardwareDeviceNames.QR &&
!this.canUseHardwareWallets()
) {
Expand Down
14 changes: 13 additions & 1 deletion development/build/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ function createScriptTasks({
// In MV3 we will need to build our offscreen entry point bundle and any
// entry points for iframes that we want to lockdown with LavaMoat.
if (process.env.ENABLE_MV3 === 'true') {
standardEntryPoints.push('offscreen');
standardEntryPoints.push('offscreen', 'trezor-iframe');
}

const standardSubtask = createTask(
Expand All @@ -321,6 +321,8 @@ function createScriptTasks({
return './app/vendor/trezor/content-script.js';
case 'offscreen':
return './offscreen/scripts/offscreen.ts';
case 'trezor-iframe':
return './offscreen/scripts/trezor-iframe.ts';
default:
return `./app/scripts/${label}.js`;
}
Expand Down Expand Up @@ -805,6 +807,16 @@ function createFactoredBuild({
});
break;
}
case 'trezor-iframe': {
renderJavaScriptLoader({
groupSet,
commonSet,
browserPlatforms,
applyLavaMoat,
destinationFileName: 'load-trezor-iframe.js',
});
break;
}
default: {
throw new Error(
`build/scripts - unknown groupLabel "${groupLabel}"`,
Expand Down
Loading

0 comments on commit b9cfbc9

Please sign in to comment.