mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Merge branch 'master' into Version-v10.15.0
This commit is contained in:
commit
3942502951
@ -17,6 +17,7 @@ ignores:
|
||||
# used in testing + ci
|
||||
- '@metamask/auto-changelog' # invoked as `auto-changelog`
|
||||
- '@metamask/forwarder'
|
||||
- '@metamask/phishing-warning' # statically hosted as part of some e2e tests
|
||||
- '@metamask/test-dapp'
|
||||
- '@metamask/design-tokens' # Only imported in index.css
|
||||
- '@tsconfig/node14' # required dynamically by TS, used in tsconfig.json
|
||||
|
@ -6,3 +6,6 @@ ONBOARDING_V2=
|
||||
SWAPS_USE_DEV_APIS=
|
||||
COLLECTIBLES_V1=
|
||||
TOKEN_DETECTION_V2=
|
||||
|
||||
; Set this to test changes to the phishing warning page.
|
||||
PHISHING_WARNING_PAGE_URL=
|
||||
|
42
CHANGELOG.md
42
CHANGELOG.md
@ -29,6 +29,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fix bug that could have caused some ledger transactions to fail after connecting Ledger then locking and unlocking ([#14563](https://github.com/MetaMask/metamask-extension/pull/14563))
|
||||
- Fix bug that could cause MetaMask to crash in some cases when attempting to send a transaction ([#14608](https://github.com/MetaMask/metamask-extension/pull/14608))
|
||||
|
||||
## [10.14.7]
|
||||
### Changed
|
||||
- Make JavaScript bundles more reproducible between environments.
|
||||
- The bundles no longer include absolute paths to each module included.
|
||||
|
||||
## [10.14.6]
|
||||
### Changed
|
||||
- Move phishing warning page to external site.
|
||||
- The page shown when a site is blocked has been extracted from the extension and moved to an external site. This site is eagerly cached with a service worker upon extension startup, so it should continue to work even while offline.
|
||||
- Make build .zip files reproducible (#14623)
|
||||
- The ordering of files within each .zip file was non-deterministic before this change. We fixed this to comply with Firefox store policies.
|
||||
|
||||
## [10.14.5]
|
||||
### Fixed
|
||||
- This release was deployed to fix a configuration issue.
|
||||
|
||||
## [10.14.4]
|
||||
### Fixed
|
||||
- This release was deployed to fix a configuration issue.
|
||||
|
||||
## [10.14.3]
|
||||
### Fixed
|
||||
- This release was deployed to fix a configuration issue.
|
||||
|
||||
## [10.14.2]
|
||||
### Fixed
|
||||
- Make build deterministic (#14610)
|
||||
- The ordering of modules within each bundle was non-deterministic before this change. We fixed this to comply with Firefox store policies.
|
||||
|
||||
## [10.14.1]
|
||||
### Changed
|
||||
- This version was used to rollback from v10.14.0 to v10.13.0.
|
||||
|
||||
## [10.14.0]
|
||||
### Added
|
||||
- **[FLASK]** Add snap version to details page ([#14110](https://github.com/MetaMask/metamask-extension/pull/14110))
|
||||
@ -2932,7 +2965,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Added the ability to restore accounts from seed words.
|
||||
|
||||
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.15.0...HEAD
|
||||
[10.15.0]: https://github.com/MetaMask/metamask-extension/compare/v10.14.0...v10.15.0
|
||||
[10.15.0]: https://github.com/MetaMask/metamask-extension/compare/v10.14.7...v10.15.0
|
||||
[10.14.7]: https://github.com/MetaMask/metamask-extension/compare/v10.14.6...v10.14.7
|
||||
[10.14.6]: https://github.com/MetaMask/metamask-extension/compare/v10.14.5...v10.14.6
|
||||
[10.14.5]: https://github.com/MetaMask/metamask-extension/compare/v10.14.4...v10.14.5
|
||||
[10.14.4]: https://github.com/MetaMask/metamask-extension/compare/v10.14.3...v10.14.4
|
||||
[10.14.3]: https://github.com/MetaMask/metamask-extension/compare/v10.14.2...v10.14.3
|
||||
[10.14.2]: https://github.com/MetaMask/metamask-extension/compare/v10.14.1...v10.14.2
|
||||
[10.14.1]: https://github.com/MetaMask/metamask-extension/compare/v10.14.0...v10.14.1
|
||||
[10.14.0]: https://github.com/MetaMask/metamask-extension/compare/v10.13.0...v10.14.0
|
||||
[10.13.0]: https://github.com/MetaMask/metamask-extension/compare/v10.12.4...v10.13.0
|
||||
[10.12.4]: https://github.com/MetaMask/metamask-extension/compare/v10.12.3...v10.12.4
|
||||
|
@ -72,6 +72,5 @@
|
||||
"*://*.eth/",
|
||||
"notifications"
|
||||
],
|
||||
"short_name": "__MSG_appName__",
|
||||
"web_accessible_resources": ["inpage.js", "phishing.html"]
|
||||
"short_name": "__MSG_appName__"
|
||||
}
|
||||
|
@ -1,150 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>MetaMask Phishing Detection</title>
|
||||
<script
|
||||
src="./globalthis.js"
|
||||
type="text/javascript"
|
||||
charset="utf-8"
|
||||
></script>
|
||||
<script
|
||||
src="./lockdown-install.js"
|
||||
type="text/javascript"
|
||||
charset="utf-8"
|
||||
></script>
|
||||
<script
|
||||
src="./lockdown-run.js"
|
||||
type="text/javascript"
|
||||
charset="utf-8"
|
||||
></script>
|
||||
<script
|
||||
src="./lockdown-more.js"
|
||||
type="text/javascript"
|
||||
charset="utf-8"
|
||||
></script>
|
||||
<script src="./phishing-detect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./index.css" title="ltr" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="./index-rtl.css"
|
||||
title="rtl"
|
||||
disabled
|
||||
/>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body,
|
||||
html {
|
||||
background-color: var(--color-error-default);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: Roboto, Arial, sans-serif;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80%;
|
||||
background-color: var(--color-background-default);
|
||||
box-shadow: 0 0 15px #737373;
|
||||
}
|
||||
.content__header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
color: var(--color-error-default);
|
||||
border-bottom: 1px solid var(--color-border-default);
|
||||
padding: 2em;
|
||||
}
|
||||
.content__header h1 {
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.content__header h1 i {
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
.content__header img {
|
||||
margin-bottom: 3em;
|
||||
width: 130px;
|
||||
}
|
||||
.content__body {
|
||||
background-color: var(--color-background-alternative);
|
||||
font-size: 12pt;
|
||||
color: var(--color-text-default);
|
||||
}
|
||||
.content__body p {
|
||||
margin: 2em;
|
||||
}
|
||||
.content__body p a {
|
||||
text-decoration: underline;
|
||||
color: var(--color-primary-default);
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div class="content__header">
|
||||
<img src="./images/logo/metamask-fox.svg" alt="MetaMask Logo" />
|
||||
<h1>
|
||||
<i class="fa fa-exclamation-circle" aria-hidden="true"></i>
|
||||
MetaMask Phishing Detection
|
||||
</h1>
|
||||
</div>
|
||||
<div class="content__body">
|
||||
<p>
|
||||
This domain is currently on the MetaMask domain warning list. This
|
||||
means that based on information available to us, MetaMask believes
|
||||
this domain could currently compromise your security and, as an added
|
||||
safety feature, MetaMask has restricted access to the site. To
|
||||
override this, please read the rest of this warning for instructions
|
||||
on how to continue at your own risk.
|
||||
</p>
|
||||
<p>
|
||||
There are many reasons sites can appear on our warning list, and our
|
||||
warning list compiles from other widely used industry lists. Such
|
||||
reasons can include known fraud or security risks, such as domains
|
||||
that test positive on the
|
||||
<a href="https://github.com/metamask/eth-phishing-detect"
|
||||
>Ethereum Phishing Detector</a
|
||||
>. Domains on these warning lists may include outright malicious
|
||||
websites and legitimate websites that have been compromised by a
|
||||
malicious actor.
|
||||
</p>
|
||||
<p>
|
||||
To read more about this site
|
||||
<a id="csdbLink" href="https://cryptoscamdb.org/search"
|
||||
>please search for the domain on CryptoScamDB</a
|
||||
>.
|
||||
</p>
|
||||
<p>
|
||||
Note that this warning list is compiled on a voluntary basis. This
|
||||
list may be inaccurate or incomplete. Just because a domain does not
|
||||
appear on this list is not an implicit guarantee of that domain's
|
||||
safety. As always, your transactions are your own responsibility. If
|
||||
you wish to interact with any domain on our warning list, you can do
|
||||
so by <a id="unsafe-continue">continuing at your own risk</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you think this domain is incorrectly flagged or if a blocked
|
||||
legitimate website has resolved its security issues,
|
||||
<a
|
||||
id="new-issue-link"
|
||||
href="https://github.com/metamask/eth-phishing-detect/issues/new"
|
||||
>please file an issue</a
|
||||
>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -67,6 +67,12 @@ if (inTest || process.env.METAMASK_DEBUG) {
|
||||
global.metamaskGetState = localStore.get.bind(localStore);
|
||||
}
|
||||
|
||||
const phishingPageUrl = new URL(process.env.PHISHING_WARNING_PAGE_URL);
|
||||
|
||||
const ONE_SECOND_IN_MILLISECONDS = 1_000;
|
||||
// Timeout for initializing phishing warning page.
|
||||
const PHISHING_WARNING_PAGE_TIMEOUT = ONE_SECOND_IN_MILLISECONDS;
|
||||
|
||||
// initialization flow
|
||||
initialize().catch(log.error);
|
||||
|
||||
@ -134,9 +140,76 @@ async function initialize() {
|
||||
const initState = await loadStateFromPersistence();
|
||||
const initLangCode = await getFirstPreferredLangCode();
|
||||
await setupController(initState, initLangCode);
|
||||
await loadPhishingWarningPage();
|
||||
log.info('MetaMask initialization complete.');
|
||||
}
|
||||
|
||||
/**
|
||||
* An error thrown if the phishing warning page takes too long to load.
|
||||
*/
|
||||
class PhishingWarningPageTimeoutError extends Error {
|
||||
constructor() {
|
||||
super('Timeout failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the phishing warning page temporarily to ensure the service
|
||||
* worker has been registered, so that the warning page works offline.
|
||||
*/
|
||||
async function loadPhishingWarningPage() {
|
||||
let iframe;
|
||||
try {
|
||||
const extensionStartupPhishingPageUrl = new URL(
|
||||
process.env.PHISHING_WARNING_PAGE_URL,
|
||||
);
|
||||
// The `extensionStartup` hash signals to the phishing warning page that it should not bother
|
||||
// setting up streams for user interaction. Otherwise this page load would cause a console
|
||||
// error.
|
||||
extensionStartupPhishingPageUrl.hash = '#extensionStartup';
|
||||
|
||||
iframe = window.document.createElement('iframe');
|
||||
iframe.setAttribute('src', extensionStartupPhishingPageUrl.href);
|
||||
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
||||
|
||||
// Create "deferred Promise" to allow passing resolve/reject to event handlers
|
||||
let deferredResolve;
|
||||
let deferredReject;
|
||||
const loadComplete = new Promise((resolve, reject) => {
|
||||
deferredResolve = resolve;
|
||||
deferredReject = reject;
|
||||
});
|
||||
|
||||
// The load event is emitted once loading has completed, even if the loading failed.
|
||||
// If loading failed we can't do anything about it, so we don't need to check.
|
||||
iframe.addEventListener('load', deferredResolve);
|
||||
|
||||
// This step initiates the page loading.
|
||||
window.document.body.appendChild(iframe);
|
||||
|
||||
// This timeout ensures that this iframe gets cleaned up in a reasonable
|
||||
// timeframe, and ensures that the "initialization complete" message
|
||||
// doesn't get delayed too long.
|
||||
setTimeout(
|
||||
() => deferredReject(new PhishingWarningPageTimeoutError()),
|
||||
PHISHING_WARNING_PAGE_TIMEOUT,
|
||||
);
|
||||
await loadComplete;
|
||||
} catch (error) {
|
||||
if (error instanceof PhishingWarningPageTimeoutError) {
|
||||
console.warn(
|
||||
'Phishing warning page timeout; page not guaraneteed to work offline.',
|
||||
);
|
||||
} else {
|
||||
console.error('Failed to initialize phishing warning page', error);
|
||||
}
|
||||
} finally {
|
||||
if (iframe) {
|
||||
iframe.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// State and Persistence
|
||||
//
|
||||
@ -362,6 +435,10 @@ function setupController(initState, initLangCode) {
|
||||
remotePort.sender.origin === `chrome-extension://${browser.runtime.id}`;
|
||||
}
|
||||
|
||||
const senderUrl = remotePort.sender?.url
|
||||
? new URL(remotePort.sender.url)
|
||||
: null;
|
||||
|
||||
if (isMetaMaskInternalProcess) {
|
||||
const portStream = new PortStream(remotePort);
|
||||
// communication with popup
|
||||
@ -406,6 +483,15 @@ function setupController(initState, initLangCode) {
|
||||
);
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
senderUrl &&
|
||||
senderUrl.origin === phishingPageUrl.origin &&
|
||||
senderUrl.pathname === phishingPageUrl.pathname
|
||||
) {
|
||||
const portStream = new PortStream(remotePort);
|
||||
controller.setupPhishingCommunication({
|
||||
connectionStream: portStream,
|
||||
});
|
||||
} else {
|
||||
if (remotePort.sender && remotePort.sender.tab && remotePort.sender.url) {
|
||||
const tabId = remotePort.sender.tab.id;
|
||||
|
@ -17,8 +17,13 @@ const inpageContent = fs.readFileSync(
|
||||
const inpageSuffix = `//# sourceURL=${browser.runtime.getURL('inpage.js')}\n`;
|
||||
const inpageBundle = inpageContent + inpageSuffix;
|
||||
|
||||
// contexts
|
||||
const CONTENT_SCRIPT = 'metamask-contentscript';
|
||||
const INPAGE = 'metamask-inpage';
|
||||
const PHISHING_WARNING_PAGE = 'metamask-phishing-warning-page';
|
||||
|
||||
// stream channels
|
||||
const PHISHING_SAFELIST = 'metamask-phishing-safelist';
|
||||
const PROVIDER = 'metamask-provider';
|
||||
|
||||
// TODO:LegacyProvider: Delete
|
||||
@ -27,7 +32,14 @@ const LEGACY_INPAGE = 'inpage';
|
||||
const LEGACY_PROVIDER = 'provider';
|
||||
const LEGACY_PUBLIC_CONFIG = 'publicConfig';
|
||||
|
||||
if (shouldInjectProvider()) {
|
||||
const phishingPageUrl = new URL(process.env.PHISHING_WARNING_PAGE_URL);
|
||||
|
||||
if (
|
||||
window.location.origin === phishingPageUrl.origin &&
|
||||
window.location.pathname === phishingPageUrl.pathname
|
||||
) {
|
||||
setupPhishingStream();
|
||||
} else if (shouldInjectProvider()) {
|
||||
injectScript(inpageBundle);
|
||||
setupStreams();
|
||||
}
|
||||
@ -50,6 +62,47 @@ function injectScript(content) {
|
||||
}
|
||||
}
|
||||
|
||||
async function setupPhishingStream() {
|
||||
// the transport-specific streams for communication between inpage and background
|
||||
const pageStream = new WindowPostMessageStream({
|
||||
name: CONTENT_SCRIPT,
|
||||
target: PHISHING_WARNING_PAGE,
|
||||
});
|
||||
const extensionPort = browser.runtime.connect({ name: CONTENT_SCRIPT });
|
||||
const extensionStream = new PortStream(extensionPort);
|
||||
|
||||
// create and connect channel muxers
|
||||
// so we can handle the channels individually
|
||||
const pageMux = new ObjectMultiplex();
|
||||
pageMux.setMaxListeners(25);
|
||||
const extensionMux = new ObjectMultiplex();
|
||||
extensionMux.setMaxListeners(25);
|
||||
|
||||
pump(pageMux, pageStream, pageMux, (err) =>
|
||||
logStreamDisconnectWarning('MetaMask Inpage Multiplex', err),
|
||||
);
|
||||
pump(extensionMux, extensionStream, extensionMux, (err) => {
|
||||
logStreamDisconnectWarning('MetaMask Background Multiplex', err);
|
||||
window.postMessage(
|
||||
{
|
||||
target: PHISHING_WARNING_PAGE, // the post-message-stream "target"
|
||||
data: {
|
||||
// this object gets passed to obj-multiplex
|
||||
name: PHISHING_SAFELIST, // the obj-multiplex channel name
|
||||
data: {
|
||||
jsonrpc: '2.0',
|
||||
method: 'METAMASK_STREAM_FAILURE',
|
||||
},
|
||||
},
|
||||
},
|
||||
window.location.origin,
|
||||
);
|
||||
});
|
||||
|
||||
// forward communication across inpage-background for these channels only
|
||||
forwardTrafficBetweenMuxes(PHISHING_SAFELIST, pageMux, extensionMux);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up two-way communication streams between the
|
||||
* browser extension and local per-page browser context.
|
||||
@ -300,9 +353,9 @@ function blockedDomainCheck() {
|
||||
* Redirects the current page to a phishing information page
|
||||
*/
|
||||
function redirectToPhishingWarning() {
|
||||
console.debug('MetaMask: Routing to Phishing Warning component.');
|
||||
const extensionURL = browser.runtime.getURL('phishing.html');
|
||||
window.location.href = `${extensionURL}#${querystring.stringify({
|
||||
console.debug('MetaMask: Routing to Phishing Warning page.');
|
||||
const baseUrl = process.env.PHISHING_WARNING_PAGE_URL;
|
||||
window.location.href = `${baseUrl}#${querystring.stringify({
|
||||
hostname: window.location.hostname,
|
||||
href: window.location.href,
|
||||
})}`;
|
||||
|
@ -27,7 +27,7 @@ const getEnvironmentTypeMemo = memoize((url) => {
|
||||
const parsedUrl = new URL(url);
|
||||
if (parsedUrl.pathname === '/popup.html') {
|
||||
return ENVIRONMENT_TYPE_POPUP;
|
||||
} else if (['/home.html', '/phishing.html'].includes(parsedUrl.pathname)) {
|
||||
} else if (['/home.html'].includes(parsedUrl.pathname)) {
|
||||
return ENVIRONMENT_TYPE_FULLSCREEN;
|
||||
} else if (parsedUrl.pathname === '/notification.html') {
|
||||
return ENVIRONMENT_TYPE_NOTIFICATION;
|
||||
|
@ -34,13 +34,6 @@ describe('app utils', () => {
|
||||
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_FULLSCREEN);
|
||||
});
|
||||
|
||||
it('should return fullscreen type for phishing.html', () => {
|
||||
const environmentType = getEnvironmentType(
|
||||
'http://extension-id/phishing.html',
|
||||
);
|
||||
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_FULLSCREEN);
|
||||
});
|
||||
|
||||
it('should return background type', () => {
|
||||
const environmentType = getEnvironmentType(
|
||||
'http://extension-id/_generated_background_page.html',
|
||||
|
@ -152,6 +152,9 @@ export const METAMASK_CONTROLLER_EVENTS = {
|
||||
APPROVAL_STATE_CHANGE: 'ApprovalController:stateChange',
|
||||
};
|
||||
|
||||
// stream channels
|
||||
const PHISHING_SAFELIST = 'metamask-phishing-safelist';
|
||||
|
||||
export default class MetamaskController extends EventEmitter {
|
||||
/**
|
||||
* @param {Object} opts
|
||||
@ -1428,7 +1431,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
),
|
||||
markPasswordForgotten: this.markPasswordForgotten.bind(this),
|
||||
unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this),
|
||||
safelistPhishingDomain: this.safelistPhishingDomain.bind(this),
|
||||
getRequestAccountTabIds: this.getRequestAccountTabIds,
|
||||
getOpenMetamaskTabsIds: this.getOpenMetamaskTabsIds,
|
||||
markNotificationPopupAsAutomaticallyClosed: () =>
|
||||
@ -3228,6 +3230,33 @@ export default class MetamaskController extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a multiplexed stream for connecting to the phishing warning page.
|
||||
*
|
||||
* @param options - Options bag.
|
||||
* @param {ReadableStream} options.connectionStream - The Duplex stream to connect to.
|
||||
*/
|
||||
setupPhishingCommunication({ connectionStream }) {
|
||||
const { usePhishDetect } = this.preferencesController.store.getState();
|
||||
|
||||
if (!usePhishDetect) {
|
||||
return;
|
||||
}
|
||||
|
||||
// setup multiplexing
|
||||
const mux = setupMultiplex(connectionStream);
|
||||
const phishingStream = mux.createStream(PHISHING_SAFELIST);
|
||||
|
||||
// set up postStream transport
|
||||
phishingStream.on(
|
||||
'data',
|
||||
createMetaRPCHandler(
|
||||
{ safelistPhishingDomain: this.safelistPhishingDomain.bind(this) },
|
||||
phishingStream,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we detect a suspicious domain. Requests the browser redirects
|
||||
* to our anti-phishing page.
|
||||
|
@ -1,40 +0,0 @@
|
||||
import querystring from 'querystring';
|
||||
import PortStream from 'extension-port-stream';
|
||||
import browser from 'webextension-polyfill';
|
||||
import createRandomId from '../../shared/modules/random-id';
|
||||
import { setupMultiplex } from './lib/stream-utils';
|
||||
import { getEnvironmentType } from './lib/util';
|
||||
import ExtensionPlatform from './platforms/extension';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', start);
|
||||
|
||||
function start() {
|
||||
const hash = window.location.hash.substring(1);
|
||||
const suspect = querystring.parse(hash);
|
||||
|
||||
const newIssueLink = document.getElementById('new-issue-link');
|
||||
const newIssueUrl = `https://github.com/MetaMask/eth-phishing-detect/issues/new`;
|
||||
const newIssueParams = `?title=[Legitimate%20Site%20Blocked]%20${encodeURIComponent(
|
||||
suspect.hostname,
|
||||
)}&body=${encodeURIComponent(suspect.href)}`;
|
||||
newIssueLink.href = `${newIssueUrl}${newIssueParams}`;
|
||||
|
||||
global.platform = new ExtensionPlatform();
|
||||
|
||||
const extensionPort = browser.runtime.connect({
|
||||
name: getEnvironmentType(),
|
||||
});
|
||||
const connectionStream = new PortStream(extensionPort);
|
||||
const mx = setupMultiplex(connectionStream);
|
||||
const backgroundConnection = mx.createStream('controller');
|
||||
const continueLink = document.getElementById('unsafe-continue');
|
||||
continueLink.addEventListener('click', () => {
|
||||
backgroundConnection.write({
|
||||
jsonrpc: '2.0',
|
||||
method: 'safelistPhishingDomain',
|
||||
params: [suspect.hostname],
|
||||
id: createRandomId(),
|
||||
});
|
||||
window.location.href = suspect.href;
|
||||
});
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
const { promises: fs } = require('fs');
|
||||
const gulp = require('gulp');
|
||||
const sort = require('gulp-sort');
|
||||
const gulpZip = require('gulp-zip');
|
||||
const del = require('del');
|
||||
const pify = require('pify');
|
||||
@ -45,7 +46,9 @@ function createZipTask(platform, buildType, version) {
|
||||
: `metamask-${buildType}-${platform}-${version}`;
|
||||
await pump(
|
||||
gulp.src(`dist/${platform}/**`),
|
||||
gulpZip(`${path}.zip`),
|
||||
// sort files and set `mtime` to epoch to ensure zip build is deterministic
|
||||
sort(),
|
||||
gulpZip(`${path}.zip`, { modifiedTime: new Date(0) }),
|
||||
gulp.dest('builds'),
|
||||
);
|
||||
};
|
||||
|
@ -34,6 +34,7 @@ const metamaskrc = require('rc')('metamask', {
|
||||
INFURA_PROD_PROJECT_ID: process.env.INFURA_PROD_PROJECT_ID,
|
||||
ONBOARDING_V2: process.env.ONBOARDING_V2,
|
||||
COLLECTIBLES_V1: process.env.COLLECTIBLES_V1,
|
||||
PHISHING_WARNING_PAGE_URL: process.env.PHISHING_WARNING_PAGE_URL,
|
||||
TOKEN_DETECTION_V2: process.env.TOKEN_DETECTION_V2,
|
||||
SEGMENT_HOST: process.env.SEGMENT_HOST,
|
||||
SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY,
|
||||
@ -133,6 +134,48 @@ function getSegmentWriteKey({ buildType, environment }) {
|
||||
throw new Error(`Invalid build type: '${buildType}'`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for the phishing warning page, if it has been set.
|
||||
*
|
||||
* @param {object} options - The phishing warning page options.
|
||||
* @param {boolean} options.testing - Whether this is a test build or not.
|
||||
* @returns {string} The URL for the phishing warning page, or `undefined` if no URL is set.
|
||||
*/
|
||||
function getPhishingWarningPageUrl({ testing }) {
|
||||
let phishingWarningPageUrl = metamaskrc.PHISHING_WARNING_PAGE_URL;
|
||||
|
||||
if (!phishingWarningPageUrl) {
|
||||
phishingWarningPageUrl = testing
|
||||
? 'http://localhost:9999/'
|
||||
: 'https://metamask.github.io/phishing-warning/v1.1.0/';
|
||||
}
|
||||
|
||||
// We add a hash/fragment to the URL dynamically, so we need to ensure it
|
||||
// has a valid pathname to append a hash to.
|
||||
const normalizedUrl = phishingWarningPageUrl.endsWith('/')
|
||||
? phishingWarningPageUrl
|
||||
: `${phishingWarningPageUrl}/`;
|
||||
|
||||
let phishingWarningPageUrlObject;
|
||||
try {
|
||||
// eslint-disable-next-line no-new
|
||||
phishingWarningPageUrlObject = new URL(normalizedUrl);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Invalid phishing warning page URL: '${normalizedUrl}'`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
if (phishingWarningPageUrlObject.hash) {
|
||||
// The URL fragment must be set dynamically
|
||||
throw new Error(
|
||||
`URL fragment not allowed in phishing warning page URL: '${normalizedUrl}'`,
|
||||
);
|
||||
}
|
||||
|
||||
return normalizedUrl;
|
||||
}
|
||||
|
||||
const noopWriteStream = through.obj((_file, _fileEncoding, callback) =>
|
||||
callback(),
|
||||
);
|
||||
@ -216,11 +259,6 @@ function createScriptTasks({
|
||||
createTaskForBundleSentry({ devMode, testing }),
|
||||
);
|
||||
|
||||
const phishingDetectSubtask = createTask(
|
||||
`${taskPrefix}:phishing-detect`,
|
||||
createTaskForBundlePhishingDetect({ devMode, testing }),
|
||||
);
|
||||
|
||||
// task for initiating browser livereload
|
||||
const initiateLiveReload = async () => {
|
||||
if (devMode) {
|
||||
@ -243,7 +281,6 @@ function createScriptTasks({
|
||||
contentscriptSubtask,
|
||||
disableConsoleSubtask,
|
||||
installSentrySubtask,
|
||||
phishingDetectSubtask,
|
||||
].map((subtask) =>
|
||||
runInChildProcess(subtask, {
|
||||
buildType,
|
||||
@ -290,23 +327,6 @@ function createScriptTasks({
|
||||
});
|
||||
}
|
||||
|
||||
function createTaskForBundlePhishingDetect({ devMode, testing }) {
|
||||
const label = 'phishing-detect';
|
||||
return createNormalBundle({
|
||||
buildType,
|
||||
browserPlatforms,
|
||||
destFilepath: `${label}.js`,
|
||||
devMode,
|
||||
entryFilepath: `./app/scripts/${label}.js`,
|
||||
ignoredFiles,
|
||||
label,
|
||||
testing,
|
||||
policyOnly,
|
||||
shouldLintFenceFiles,
|
||||
version,
|
||||
});
|
||||
}
|
||||
|
||||
// the "contentscript" bundle contains the "inpage" bundle
|
||||
function createTaskForBundleContentscript({ devMode, testing }) {
|
||||
const inpage = 'inpage';
|
||||
@ -818,6 +838,7 @@ function getEnvironmentVariables({ buildType, devMode, testing, version }) {
|
||||
METAMASK_BUILD_TYPE: buildType,
|
||||
NODE_ENV: devMode ? ENVIRONMENT.DEVELOPMENT : ENVIRONMENT.PRODUCTION,
|
||||
IN_TEST: testing,
|
||||
PHISHING_WARNING_PAGE_URL: getPhishingWarningPageUrl({ testing }),
|
||||
PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '',
|
||||
PUBNUB_PUB_KEY: process.env.PUBNUB_PUB_KEY || '',
|
||||
CONF: devMode ? metamaskrc : {},
|
||||
|
@ -174,10 +174,6 @@ function getCopyTargets(shouldIncludeLockdown) {
|
||||
src: require.resolve('@lavamoat/lavapack/src/runtime.js'),
|
||||
dest: `runtime-lavamoat.js`,
|
||||
},
|
||||
{
|
||||
src: `./app/phishing.html`,
|
||||
dest: `phishing.html`,
|
||||
},
|
||||
];
|
||||
|
||||
const languageTags = new Set();
|
||||
|
@ -24,7 +24,6 @@ async function start() {
|
||||
`common-0.js`,
|
||||
`background-0.js`,
|
||||
`ui-0.js`,
|
||||
'phishing-detect.js',
|
||||
// `contentscript.js`, skipped because the validator is erroneously sampling the inlined `inpage.js` script
|
||||
`inpage.js`,
|
||||
];
|
||||
|
@ -3171,7 +3171,7 @@
|
||||
"gulp-autoprefixer>autoprefixer": true,
|
||||
"gulp-autoprefixer>postcss": true,
|
||||
"gulp-autoprefixer>through2": true,
|
||||
"gulp-watch>plugin-error": true,
|
||||
"gulp-zip>plugin-error": true,
|
||||
"vinyl-sourcemaps-apply": true
|
||||
}
|
||||
},
|
||||
@ -3289,7 +3289,7 @@
|
||||
"gulp-dart-sass>lodash.clonedeep": true,
|
||||
"gulp-dart-sass>strip-ansi": true,
|
||||
"gulp-dart-sass>through2": true,
|
||||
"gulp-watch>plugin-error": true,
|
||||
"gulp-zip>plugin-error": true,
|
||||
"sass": true,
|
||||
"vinyl-sourcemaps-apply": true,
|
||||
"vinyl>replace-ext": true
|
||||
@ -3589,7 +3589,7 @@
|
||||
"packages": {
|
||||
"gulp-rtlcss>rtlcss": true,
|
||||
"gulp-rtlcss>through2": true,
|
||||
"gulp-watch>plugin-error": true,
|
||||
"gulp-zip>plugin-error": true,
|
||||
"vinyl-sourcemaps-apply": true
|
||||
}
|
||||
},
|
||||
@ -3685,6 +3685,23 @@
|
||||
"watchify>xtend": true
|
||||
}
|
||||
},
|
||||
"gulp-sort": {
|
||||
"packages": {
|
||||
"gulp-sort>through2": true
|
||||
}
|
||||
},
|
||||
"gulp-sort>through2": {
|
||||
"builtin": {
|
||||
"util.inherits": true
|
||||
},
|
||||
"globals": {
|
||||
"process.nextTick": true
|
||||
},
|
||||
"packages": {
|
||||
"readable-stream": true,
|
||||
"watchify>xtend": true
|
||||
}
|
||||
},
|
||||
"gulp-sourcemaps": {
|
||||
"builtin": {
|
||||
"path.dirname": true,
|
||||
@ -3898,7 +3915,7 @@
|
||||
"eslint>strip-ansi": true,
|
||||
"fancy-log": true,
|
||||
"gulp-stylelint>through2": true,
|
||||
"gulp-watch>plugin-error": true,
|
||||
"gulp-zip>plugin-error": true,
|
||||
"source-map": true,
|
||||
"stylelint": true
|
||||
}
|
||||
@ -3953,9 +3970,9 @@
|
||||
"gulp-watch>fancy-log": true,
|
||||
"gulp-watch>glob-parent": true,
|
||||
"gulp-watch>path-is-absolute": true,
|
||||
"gulp-watch>plugin-error": true,
|
||||
"gulp-watch>slash": true,
|
||||
"gulp-watch>vinyl-file": true,
|
||||
"gulp-zip>plugin-error": true,
|
||||
"react>object-assign": true,
|
||||
"readable-stream": true,
|
||||
"vinyl": true
|
||||
@ -4480,28 +4497,6 @@
|
||||
"process.platform": true
|
||||
}
|
||||
},
|
||||
"gulp-watch>plugin-error": {
|
||||
"builtin": {
|
||||
"util.inherits": true
|
||||
},
|
||||
"packages": {
|
||||
"gulp-watch>ansi-colors": true,
|
||||
"gulp-watch>plugin-error>arr-union": true,
|
||||
"gulp-watch>plugin-error>extend-shallow": true,
|
||||
"webpack>micromatch>arr-diff": true
|
||||
}
|
||||
},
|
||||
"gulp-watch>plugin-error>extend-shallow": {
|
||||
"packages": {
|
||||
"gulp-watch>plugin-error>extend-shallow>is-extendable": true,
|
||||
"webpack>micromatch>extend-shallow>assign-symbols": true
|
||||
}
|
||||
},
|
||||
"gulp-watch>plugin-error>extend-shallow>is-extendable": {
|
||||
"packages": {
|
||||
"gulp>gulp-cli>liftoff>is-plain-object": true
|
||||
}
|
||||
},
|
||||
"gulp-watch>vinyl-file": {
|
||||
"builtin": {
|
||||
"path.resolve": true
|
||||
@ -4584,6 +4579,7 @@
|
||||
},
|
||||
"gulp-zip": {
|
||||
"builtin": {
|
||||
"buffer.constants.MAX_LENGTH": true,
|
||||
"path.join": true
|
||||
},
|
||||
"packages": {
|
||||
@ -4596,10 +4592,14 @@
|
||||
},
|
||||
"gulp-zip>get-stream": {
|
||||
"builtin": {
|
||||
"buffer.constants.MAX_LENGTH": true,
|
||||
"stream.PassThrough": true
|
||||
},
|
||||
"globals": {
|
||||
"Buffer.concat": true
|
||||
},
|
||||
"packages": {
|
||||
"pump": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>plugin-error": {
|
||||
@ -4607,37 +4607,21 @@
|
||||
"util.inherits": true
|
||||
},
|
||||
"packages": {
|
||||
"gulp-zip>plugin-error>ansi-cyan": true,
|
||||
"gulp-zip>plugin-error>ansi-red": true,
|
||||
"gulp-zip>plugin-error>arr-diff": true,
|
||||
"gulp-watch>ansi-colors": true,
|
||||
"gulp-zip>plugin-error>arr-union": true,
|
||||
"gulp-zip>plugin-error>extend-shallow": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>plugin-error>ansi-cyan": {
|
||||
"packages": {
|
||||
"fancy-log>ansi-gray>ansi-wrap": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>plugin-error>ansi-red": {
|
||||
"packages": {
|
||||
"fancy-log>ansi-gray>ansi-wrap": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>plugin-error>arr-diff": {
|
||||
"packages": {
|
||||
"gulp-zip>plugin-error>arr-diff>array-slice": true,
|
||||
"gulp>undertaker>arr-flatten": true
|
||||
"gulp-zip>plugin-error>extend-shallow": true,
|
||||
"webpack>micromatch>arr-diff": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>plugin-error>extend-shallow": {
|
||||
"packages": {
|
||||
"gulp-zip>plugin-error>extend-shallow>kind-of": true
|
||||
"gulp-zip>plugin-error>extend-shallow>is-extendable": true,
|
||||
"webpack>micromatch>extend-shallow>assign-symbols": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>plugin-error>extend-shallow>kind-of": {
|
||||
"globals": {
|
||||
"Buffer": true
|
||||
"gulp-zip>plugin-error>extend-shallow>is-extendable": {
|
||||
"packages": {
|
||||
"gulp>gulp-cli>liftoff>is-plain-object": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>through2": {
|
||||
@ -4648,8 +4632,26 @@
|
||||
"process.nextTick": true
|
||||
},
|
||||
"packages": {
|
||||
"readable-stream": true,
|
||||
"watchify>xtend": true
|
||||
"gulp-zip>through2>readable-stream": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>through2>readable-stream": {
|
||||
"builtin": {
|
||||
"buffer.Buffer": true,
|
||||
"events.EventEmitter": true,
|
||||
"stream": true,
|
||||
"util": true
|
||||
},
|
||||
"globals": {
|
||||
"process.env.READABLE_STREAM": true,
|
||||
"process.nextTick": true,
|
||||
"process.stderr": true,
|
||||
"process.stdout": true
|
||||
},
|
||||
"packages": {
|
||||
"@storybook/api>util-deprecate": true,
|
||||
"browserify>string_decoder": true,
|
||||
"pumpify>inherits": true
|
||||
}
|
||||
},
|
||||
"gulp-zip>yazl": {
|
||||
@ -5417,7 +5419,7 @@
|
||||
},
|
||||
"lavamoat-browserify>merge-deep": {
|
||||
"packages": {
|
||||
"gulp-watch>plugin-error>arr-union": true,
|
||||
"gulp-zip>plugin-error>arr-union": true,
|
||||
"lavamoat-browserify>merge-deep>clone-deep": true,
|
||||
"lavamoat-browserify>merge-deep>kind-of": true
|
||||
}
|
||||
@ -7405,7 +7407,7 @@
|
||||
},
|
||||
"webpack>micromatch>snapdragon>base>cache-base>union-value": {
|
||||
"packages": {
|
||||
"gulp-watch>plugin-error>arr-union": true,
|
||||
"gulp-zip>plugin-error>arr-union": true,
|
||||
"gulp>gulp-cli>array-sort>get-value": true,
|
||||
"webpack>micromatch>extglob>extend-shallow>is-extendable": true,
|
||||
"webpack>micromatch>snapdragon>base>cache-base>set-value": true
|
||||
@ -7434,7 +7436,7 @@
|
||||
"util": true
|
||||
},
|
||||
"packages": {
|
||||
"gulp-watch>plugin-error>arr-union": true,
|
||||
"gulp-zip>plugin-error>arr-union": true,
|
||||
"gulp>gulp-cli>isobject": true,
|
||||
"webpack>micromatch>snapdragon>base>class-utils>static-extend": true,
|
||||
"webpack>micromatch>snapdragon>define-property": true
|
||||
|
@ -251,6 +251,7 @@
|
||||
"@metamask/eslint-config-nodejs": "^9.0.0",
|
||||
"@metamask/eslint-config-typescript": "^9.0.1",
|
||||
"@metamask/forwarder": "^1.1.0",
|
||||
"@metamask/phishing-warning": "^1.1.0",
|
||||
"@metamask/test-dapp": "^5.0.0",
|
||||
"@sentry/cli": "^1.58.0",
|
||||
"@storybook/addon-a11y": "^6.3.12",
|
||||
@ -276,7 +277,7 @@
|
||||
"@typescript-eslint/parser": "^4.20.0",
|
||||
"addons-linter": "1.14.0",
|
||||
"babelify": "^10.0.0",
|
||||
"bify-module-groups": "^1.0.0",
|
||||
"bify-module-groups": "^2.0.0",
|
||||
"brfs": "^2.0.2",
|
||||
"browser-util-inspect": "^0.2.0",
|
||||
"browserify": "^16.5.1",
|
||||
@ -317,10 +318,11 @@
|
||||
"gulp-livereload": "4.0.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-rtlcss": "^1.4.0",
|
||||
"gulp-sort": "^2.0.0",
|
||||
"gulp-sourcemaps": "^3.0.0",
|
||||
"gulp-stylelint": "^13.0.0",
|
||||
"gulp-watch": "^5.0.1",
|
||||
"gulp-zip": "^4.0.0",
|
||||
"gulp-zip": "^5.1.0",
|
||||
"history": "^5.0.0",
|
||||
"improved-yarn-audit": "^3.0.0",
|
||||
"jest": "^26.6.3",
|
||||
|
15
patches/@lavamoat+lavapack+2.0.4.patch
Normal file
15
patches/@lavamoat+lavapack+2.0.4.patch
Normal file
@ -0,0 +1,15 @@
|
||||
diff --git a/node_modules/@lavamoat/lavapack/src/pack.js b/node_modules/@lavamoat/lavapack/src/pack.js
|
||||
index 8e5284f..f0e4a64 100644
|
||||
--- a/node_modules/@lavamoat/lavapack/src/pack.js
|
||||
+++ b/node_modules/@lavamoat/lavapack/src/pack.js
|
||||
@@ -204,7 +204,9 @@ function createPacker({
|
||||
// id,
|
||||
package: packageName,
|
||||
packageVersion,
|
||||
- file,
|
||||
+ // Omit this absolute filename from bundle so that builds are reproducible between environments
|
||||
+ // TODO: update lavapack with an option to omit this, and/or make this filepath relative to the current working directory
|
||||
+ // file,
|
||||
// deps,
|
||||
// source: sourceMeta.code
|
||||
}
|
@ -6,6 +6,7 @@ const enLocaleMessages = require('../../app/_locales/en/messages.json');
|
||||
const { setupMocking } = require('./mock-e2e');
|
||||
const Ganache = require('./ganache');
|
||||
const FixtureServer = require('./fixture-server');
|
||||
const PhishingWarningPageServer = require('./phishing-warning-page-server');
|
||||
const { buildWebDriver } = require('./webdriver');
|
||||
const { ensureXServerIsRunning } = require('./x-server');
|
||||
|
||||
@ -27,6 +28,7 @@ async function withFixtures(options, testSuite) {
|
||||
title,
|
||||
failOnConsoleError = true,
|
||||
dappPath = undefined,
|
||||
dappPaths,
|
||||
testSpecificMock = function () {
|
||||
// do nothing.
|
||||
},
|
||||
@ -38,6 +40,7 @@ async function withFixtures(options, testSuite) {
|
||||
let secondaryGanacheServer;
|
||||
let numberOfDapps = dapp ? 1 : 0;
|
||||
const dappServer = [];
|
||||
const phishingPageServer = new PhishingWarningPageServer();
|
||||
|
||||
let webDriver;
|
||||
let failed = false;
|
||||
@ -55,14 +58,15 @@ async function withFixtures(options, testSuite) {
|
||||
}
|
||||
await fixtureServer.start();
|
||||
await fixtureServer.loadState(path.join(__dirname, 'fixtures', fixtures));
|
||||
await phishingPageServer.start();
|
||||
if (dapp) {
|
||||
if (dappOptions?.numberOfDapps) {
|
||||
numberOfDapps = dappOptions.numberOfDapps;
|
||||
}
|
||||
for (let i = 0; i < numberOfDapps; i++) {
|
||||
let dappDirectory;
|
||||
if (dappPath) {
|
||||
dappDirectory = path.resolve(__dirname, dappPath);
|
||||
if (dappPath || (dappPaths && dappPaths[i])) {
|
||||
dappDirectory = path.resolve(__dirname, dappPath || dappPaths[i]);
|
||||
} else {
|
||||
dappDirectory = path.resolve(
|
||||
__dirname,
|
||||
@ -146,6 +150,9 @@ async function withFixtures(options, testSuite) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (phishingPageServer.isRunning()) {
|
||||
await phishingPageServer.quit();
|
||||
}
|
||||
await mockServer.stop();
|
||||
}
|
||||
}
|
||||
|
20
test/e2e/mock-page-with-disallowed-iframe/index.html
Normal file
20
test/e2e/mock-page-with-disallowed-iframe/index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Mock E2E Phishing Page</title>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function setIframeSource() {
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
const extensionUrl = new URL(params.extensionUrl);
|
||||
document.getElementById('frame').src = `http://localhost:9999/#hostname=${encodeURIComponent(extensionUrl.hostname)}&href=${encodeURIComponent(extensionUrl.href)}`;
|
||||
}
|
||||
window.onload = setIframeSource;
|
||||
</script>
|
||||
<body>
|
||||
<div>Hello</div>
|
||||
<iframe id="frame" width=900 height=900>
|
||||
</body>
|
||||
|
||||
</html>
|
11
test/e2e/mock-page-with-iframe/index.html
Normal file
11
test/e2e/mock-page-with-iframe/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Mock E2E Phishing Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>Hello</div>
|
||||
<iframe src="http://127.0.0.1:8081" width=900 height=900>
|
||||
</body>
|
||||
|
||||
</html>
|
58
test/e2e/phishing-warning-page-server.js
Normal file
58
test/e2e/phishing-warning-page-server.js
Normal file
@ -0,0 +1,58 @@
|
||||
const path = require('path');
|
||||
const createStaticServer = require('../../development/create-static-server');
|
||||
|
||||
const phishingWarningDirectory = path.resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'node_modules',
|
||||
'@metamask',
|
||||
'phishing-warning',
|
||||
'dist',
|
||||
);
|
||||
|
||||
class PhishingWarningPageServer {
|
||||
constructor() {
|
||||
this._server = createStaticServer(phishingWarningDirectory);
|
||||
}
|
||||
|
||||
async start({ port = 9999 } = {}) {
|
||||
this._server.listen(port);
|
||||
|
||||
let resolveStart;
|
||||
let rejectStart;
|
||||
const result = new Promise((resolve, reject) => {
|
||||
resolveStart = resolve;
|
||||
rejectStart = reject;
|
||||
});
|
||||
this._server.once('listening', resolveStart);
|
||||
this._server.once('error', rejectStart);
|
||||
|
||||
try {
|
||||
await result;
|
||||
// clean up listener to ensure later errors properly bubble up
|
||||
this._server.removeListener('error', rejectStart);
|
||||
} catch (error) {
|
||||
this._server.removeListener('listening', resolveStart);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
isRunning() {
|
||||
return this._server.listening;
|
||||
}
|
||||
|
||||
async quit() {
|
||||
await new Promise((resolve, reject) =>
|
||||
this._server.close((error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PhishingWarningPageServer;
|
@ -15,7 +15,7 @@ describe('Phishing Detection', function () {
|
||||
tolerance: 2,
|
||||
fuzzylist: [],
|
||||
whitelist: [],
|
||||
blacklist: ['example.com'],
|
||||
blacklist: ['127.0.0.1'],
|
||||
},
|
||||
};
|
||||
});
|
||||
@ -29,22 +29,105 @@ describe('Phishing Detection', function () {
|
||||
},
|
||||
],
|
||||
};
|
||||
it('should display the MetaMask Phishing Detection page', async function () {
|
||||
it('should display the MetaMask Phishing Detection page and take the user to the blocked page if they continue', async function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: 'imported-account',
|
||||
ganacheOptions,
|
||||
title: this.test.title,
|
||||
testSpecificMock: mockPhishingDetection,
|
||||
dapp: true,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
async ({ driver }) => {
|
||||
await driver.navigate();
|
||||
await driver.fill('#password', 'correct horse battery staple');
|
||||
await driver.press('#password', driver.Key.ENTER);
|
||||
await driver.openNewPage('http://example.com');
|
||||
await driver.waitForSelector({ text: 'continuing at your own risk' });
|
||||
await driver.openNewPage('http://127.0.0.1:8080');
|
||||
await driver.clickElement({
|
||||
text: 'continuing at your own risk',
|
||||
});
|
||||
const header = await driver.findElement('h1');
|
||||
assert.equal(await header.getText(), 'MetaMask Phishing Detection');
|
||||
assert.equal(await header.getText(), 'E2E Test Dapp');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the MetaMask Phishing Detection page in an iframe and take the user to the blocked page if they continue', async function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: 'imported-account',
|
||||
ganacheOptions,
|
||||
title: this.test.title,
|
||||
testSpecificMock: mockPhishingDetection,
|
||||
dapp: true,
|
||||
dappPaths: ['mock-page-with-iframe'],
|
||||
dappOptions: {
|
||||
numberOfDapps: 2,
|
||||
},
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
async ({ driver }) => {
|
||||
await driver.navigate();
|
||||
await driver.fill('#password', 'correct horse battery staple');
|
||||
await driver.press('#password', driver.Key.ENTER);
|
||||
await driver.openNewPage('http://localhost:8080/');
|
||||
|
||||
const iframe = await driver.findElement('iframe');
|
||||
|
||||
await driver.switchToFrame(iframe);
|
||||
await driver.clickElement({
|
||||
text: 'Open this warning in a new tab',
|
||||
});
|
||||
await driver.switchToWindowWithTitle('MetaMask Phishing Detection');
|
||||
await driver.clickElement({
|
||||
text: 'continuing at your own risk',
|
||||
});
|
||||
const header = await driver.findElement('h1');
|
||||
assert.equal(await header.getText(), 'E2E Test Dapp');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the MetaMask Phishing Detection page in an iframe but should NOT take the user to the blocked page if it is not an accessible resource', async function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: 'imported-account',
|
||||
ganacheOptions,
|
||||
title: this.test.title,
|
||||
testSpecificMock: mockPhishingDetection,
|
||||
dapp: true,
|
||||
dappPaths: ['mock-page-with-disallowed-iframe'],
|
||||
dappOptions: {
|
||||
numberOfDapps: 2,
|
||||
},
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
async ({ driver }) => {
|
||||
await driver.navigate();
|
||||
await driver.fill('#password', 'correct horse battery staple');
|
||||
await driver.press('#password', driver.Key.ENTER);
|
||||
await driver.openNewPage(
|
||||
`http://localhost:8080?extensionUrl=${driver.extensionUrl}`,
|
||||
);
|
||||
|
||||
const iframe = await driver.findElement('iframe');
|
||||
|
||||
await driver.switchToFrame(iframe);
|
||||
await driver.clickElement({
|
||||
text: 'Open this warning in a new tab',
|
||||
});
|
||||
await driver.switchToWindowWithTitle('MetaMask Phishing Detection');
|
||||
await driver.clickElement({
|
||||
text: 'continuing at your own risk',
|
||||
});
|
||||
|
||||
// Ensure we're not on the wallet home page
|
||||
await driver.assertElementNotPresent('[data-testid="wallet-balance"]');
|
||||
// Ensure we're still on the warning page, meaning that the navigation failed
|
||||
await driver.findElement({
|
||||
text: 'continuing at your own risk',
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -304,6 +304,10 @@ class Driver {
|
||||
await this.driver.switchTo().window(handle);
|
||||
}
|
||||
|
||||
async switchToFrame(element) {
|
||||
await this.driver.switchTo().frame(element);
|
||||
}
|
||||
|
||||
async getAllWindowHandles() {
|
||||
return await this.driver.getAllWindowHandles();
|
||||
}
|
||||
|
136
yarn.lock
136
yarn.lock
@ -2812,10 +2812,10 @@
|
||||
web3 "^0.20.7"
|
||||
web3-provider-engine "^16.0.3"
|
||||
|
||||
"@metamask/design-tokens@^1.5.1":
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@metamask/design-tokens/-/design-tokens-1.5.1.tgz#723f10bc5fe03ce14d47b1ad6190a835df62745a"
|
||||
integrity sha512-HLXpuzQGnVPZHOvHpzOVQoe/1mvjNOTNxvAgR1na3BAUiO3NhnUxhYE2RzV0rpbc3UUUGbjVB+dceMZ4FtFfRw==
|
||||
"@metamask/design-tokens@^1.5.1", "@metamask/design-tokens@^1.6.0":
|
||||
version "1.6.5"
|
||||
resolved "https://registry.yarnpkg.com/@metamask/design-tokens/-/design-tokens-1.6.5.tgz#e585b67f73ce301e0218d98ba89e079f7e81c412"
|
||||
integrity sha512-5eCrUHXrIivXX1xx6kwNtM9s/ejhrPYSATSniFc7YKS9z+TkCK4/n52owOBnDIbrL8W3XxQIiaaqQAM+NQad4w==
|
||||
|
||||
"@metamask/eslint-config-jest@^9.0.0":
|
||||
version "9.0.0"
|
||||
@ -2973,6 +2973,18 @@
|
||||
"@metamask/safe-event-emitter" "^2.0.0"
|
||||
through2 "^2.0.3"
|
||||
|
||||
"@metamask/phishing-warning@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@metamask/phishing-warning/-/phishing-warning-1.1.0.tgz#0d5764327c413dd1900db786e295bd729530ca66"
|
||||
integrity sha512-39N7lU9fdkXZKHn/hbkiEhv1oJ3mabPjYMk22582a7XzdBD5wgxDf5qHsXXQlOq+uI3lBU9VVKD7K7Z2lcgapw==
|
||||
dependencies:
|
||||
"@metamask/design-tokens" "^1.6.0"
|
||||
"@metamask/post-message-stream" "^4.0.0"
|
||||
globalthis "1.0.1"
|
||||
obj-multiplex "^1.0.0"
|
||||
pump "^3.0.0"
|
||||
ses "0.12.4"
|
||||
|
||||
"@metamask/post-message-stream@4.0.0", "@metamask/post-message-stream@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@metamask/post-message-stream/-/post-message-stream-4.0.0.tgz#72f120e562346ca86ccc9b3684023ad44265f0df"
|
||||
@ -5609,13 +5621,6 @@ ansi-colors@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
||||
|
||||
ansi-cyan@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873"
|
||||
integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=
|
||||
dependencies:
|
||||
ansi-wrap "0.1.0"
|
||||
|
||||
ansi-escapes@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
|
||||
@ -5645,13 +5650,6 @@ ansi-html@0.0.7, ansi-html@^0.0.7:
|
||||
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
|
||||
integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
|
||||
|
||||
ansi-red@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c"
|
||||
integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=
|
||||
dependencies:
|
||||
ansi-wrap "0.1.0"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
@ -5815,14 +5813,6 @@ arity-n@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745"
|
||||
integrity sha1-2edrEXM+CFacCEeuezmyhgswt0U=
|
||||
|
||||
arr-diff@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a"
|
||||
integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo=
|
||||
dependencies:
|
||||
arr-flatten "^1.0.1"
|
||||
array-slice "^0.2.3"
|
||||
|
||||
arr-diff@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
|
||||
@ -5854,11 +5844,6 @@ arr-map@^2.0.0, arr-map@^2.0.2:
|
||||
dependencies:
|
||||
make-iterator "^1.0.0"
|
||||
|
||||
arr-union@^2.0.1:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d"
|
||||
integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=
|
||||
|
||||
arr-union@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
|
||||
@ -5920,11 +5905,6 @@ array-last@^1.1.1:
|
||||
dependencies:
|
||||
is-number "^4.0.0"
|
||||
|
||||
array-slice@^0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
|
||||
integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU=
|
||||
|
||||
array-slice@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4"
|
||||
@ -6659,24 +6639,14 @@ better-opn@^2.1.1:
|
||||
dependencies:
|
||||
open "^7.0.3"
|
||||
|
||||
bify-module-groups@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bify-module-groups/-/bify-module-groups-1.0.0.tgz#6fba8f96a8b0f9e8f0b04035650fd56249b6119d"
|
||||
integrity sha512-JAAkE9L5vZoALCEqawXipQNlDn3D0nUyjt0cHgRXj0Kce2RNLQsBxA6wTmnYpQDna6g6VVyC8IUi3n02ppmbhA==
|
||||
bify-module-groups@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bify-module-groups/-/bify-module-groups-2.0.0.tgz#b629b0028db855b7a587d932ea3af7ed4a69dca9"
|
||||
integrity sha512-9hkVBhhjO5ycUGlUT6KW109gOgsmnrDH+vMjPFFkY9oCiP397p5o4wruXZqyI9ZA1p8hA5egoKBoh3GwbKiM4g==
|
||||
dependencies:
|
||||
bify-packagedata-stream "1.0.0"
|
||||
pump "^3.0.0"
|
||||
through2 "^3.0.1"
|
||||
|
||||
bify-packagedata-stream@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bify-packagedata-stream/-/bify-packagedata-stream-1.0.0.tgz#a6dbdcba64f9bf1c87bdc02ba9586fff7b94ccb3"
|
||||
integrity sha512-ckOCceDpAOySFrt89saOShpVbP/iQbmZeWlYSxZV2e3HPTPhcd3JSudMJZhpsihQTyZut39efDo4+8aOb4vo2w==
|
||||
dependencies:
|
||||
module-name-from-path "git+https://git@github.com/kumavis/module-name-from-path.git"
|
||||
resolve-package-path "^1.2.7"
|
||||
through2 "^3.0.0"
|
||||
|
||||
big-integer@1.6.36:
|
||||
version "1.6.36"
|
||||
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36"
|
||||
@ -12033,13 +12003,6 @@ express@^4.14.0, express@^4.17.1:
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
extend-shallow@^1.1.2:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071"
|
||||
integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=
|
||||
dependencies:
|
||||
kind-of "^1.1.0"
|
||||
|
||||
extend-shallow@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
|
||||
@ -13147,7 +13110,7 @@ get-stream@^4.0.0, get-stream@^4.1.0:
|
||||
dependencies:
|
||||
pump "^3.0.0"
|
||||
|
||||
get-stream@^5.0.0, get-stream@^5.1.0:
|
||||
get-stream@^5.0.0, get-stream@^5.1.0, get-stream@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
|
||||
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
|
||||
@ -13437,7 +13400,7 @@ globals@^9.14.0:
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
|
||||
|
||||
globalthis@^1.0.0, globalthis@^1.0.1:
|
||||
globalthis@1.0.1, globalthis@^1.0.0, globalthis@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9"
|
||||
integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==
|
||||
@ -13727,6 +13690,13 @@ gulp-rtlcss@^1.4.0:
|
||||
through2 "^2.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.1"
|
||||
|
||||
gulp-sort@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/gulp-sort/-/gulp-sort-2.0.0.tgz#c6762a2f1f0de0a3fc595a21599d3fac8dba1aca"
|
||||
integrity sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=
|
||||
dependencies:
|
||||
through2 "^2.0.1"
|
||||
|
||||
gulp-sourcemaps@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz#2e154e1a2efed033c0e48013969e6f30337b2743"
|
||||
@ -13774,16 +13744,16 @@ gulp-watch@^5.0.1:
|
||||
vinyl "^2.1.0"
|
||||
vinyl-file "^2.0.0"
|
||||
|
||||
gulp-zip@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/gulp-zip/-/gulp-zip-4.1.0.tgz#dab178bd99afa190923f1eb78abaf0db47817704"
|
||||
integrity sha1-2rF4vZmvoZCSPx63irrw20eBdwQ=
|
||||
gulp-zip@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/gulp-zip/-/gulp-zip-5.1.0.tgz#38cc1d4c61bc2ab06b452ce463cbe2adc52b935e"
|
||||
integrity sha512-XZr/y91IliK/SpR74g3TkZejGkGEmK7CSDjSghT1jXshgO+dFvpLIz9w9fpuwkew6i7k4F+G24TubNgq1ISzEw==
|
||||
dependencies:
|
||||
get-stream "^3.0.0"
|
||||
plugin-error "^0.1.2"
|
||||
through2 "^2.0.1"
|
||||
get-stream "^5.2.0"
|
||||
plugin-error "^1.0.1"
|
||||
through2 "^3.0.1"
|
||||
vinyl "^2.1.0"
|
||||
yazl "^2.1.0"
|
||||
yazl "^2.5.1"
|
||||
|
||||
gulp@^4.0.2:
|
||||
version "4.0.2"
|
||||
@ -17076,11 +17046,6 @@ keyv@^3.0.0:
|
||||
dependencies:
|
||||
json-buffer "3.0.0"
|
||||
|
||||
kind-of@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44"
|
||||
integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=
|
||||
|
||||
kind-of@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5"
|
||||
@ -19269,10 +19234,6 @@ module-lookup-amd@^7.0.0:
|
||||
requirejs "^2.3.5"
|
||||
requirejs-config-file "^4.0.0"
|
||||
|
||||
"module-name-from-path@git+https://git@github.com/kumavis/module-name-from-path.git":
|
||||
version "1.0.4"
|
||||
resolved "git+https://git@github.com/kumavis/module-name-from-path.git#fd9c592663a1af6cc48b1be7b8045ea547fca79a"
|
||||
|
||||
module-not-found-error@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0"
|
||||
@ -21551,17 +21512,6 @@ plugin-error@1.0.1, plugin-error@^1.0.1:
|
||||
arr-union "^3.1.0"
|
||||
extend-shallow "^3.0.2"
|
||||
|
||||
plugin-error@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace"
|
||||
integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=
|
||||
dependencies:
|
||||
ansi-cyan "^0.1.1"
|
||||
ansi-red "^0.1.1"
|
||||
arr-diff "^1.0.1"
|
||||
arr-union "^2.0.1"
|
||||
extend-shallow "^1.1.2"
|
||||
|
||||
pluralize@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
|
||||
@ -23948,14 +23898,6 @@ resolve-options@^1.1.0:
|
||||
dependencies:
|
||||
value-or-function "^3.0.0"
|
||||
|
||||
resolve-package-path@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e"
|
||||
integrity sha512-fVEKHGeK85bGbVFuwO9o1aU0n3vqQGrezPc51JGu9UTXpFQfWq5qCeKxyaRUSvephs+06c5j5rPq/dzHGEo8+Q==
|
||||
dependencies:
|
||||
path-root "^0.1.1"
|
||||
resolve "^1.10.0"
|
||||
|
||||
resolve-pathname@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
|
||||
@ -24635,7 +24577,7 @@ serve-static@1.14.1:
|
||||
parseurl "~1.3.3"
|
||||
send "0.17.1"
|
||||
|
||||
ses@^0.12.4:
|
||||
ses@0.12.4, ses@^0.12.4:
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/ses/-/ses-0.12.4.tgz#f466f7199292b5c4454949c7d497f5569ade5805"
|
||||
integrity sha512-qbtkhuuAXNXb390yiaNUdNvDg/QmX7W2cO+srIUJllINMYADc/8m0vt7DNBmq+rqOBRrjVRPPeyQq8ZTLK3Rmw==
|
||||
@ -28443,7 +28385,7 @@ yauzl@2.10.0, yauzl@^2.10.0:
|
||||
buffer-crc32 "~0.2.3"
|
||||
fd-slicer "~1.1.0"
|
||||
|
||||
yazl@^2.1.0:
|
||||
yazl@^2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"
|
||||
integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==
|
||||
|
Loading…
Reference in New Issue
Block a user