@polkadot/extension-base 0.60.1 → 0.61.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/background/handlers/State.d.ts +1 -0
- package/background/handlers/State.js +22 -0
- package/background/handlers/Tabs.d.ts +1 -0
- package/background/handlers/Tabs.js +16 -1
- package/cjs/background/handlers/State.d.ts +1 -0
- package/cjs/background/handlers/State.js +22 -0
- package/cjs/background/handlers/Tabs.d.ts +1 -0
- package/cjs/background/handlers/Tabs.js +16 -1
- package/cjs/packageInfo.js +1 -1
- package/package.json +5 -4
- package/packageInfo.js +1 -1
|
@@ -90,6 +90,7 @@ export default class State {
|
|
|
90
90
|
rpcUnsubscribe(request: RequestRpcUnsubscribe, port: chrome.runtime.Port): Promise<boolean>;
|
|
91
91
|
saveMetadata(meta: MetadataDef): Promise<void>;
|
|
92
92
|
setNotification(notification: string): boolean;
|
|
93
|
+
private handleSignRequest;
|
|
93
94
|
sign(url: string, request: RequestSign, account: AccountJson): Promise<ResponseSigning>;
|
|
94
95
|
}
|
|
95
96
|
export {};
|
|
@@ -64,6 +64,9 @@ async function extractMetadata(store) {
|
|
|
64
64
|
}
|
|
65
65
|
export default class State {
|
|
66
66
|
#authUrls = new Map();
|
|
67
|
+
#lastRequestTimestamps = new Map();
|
|
68
|
+
#maxEntries = 10;
|
|
69
|
+
#rateLimitInterval = 3000; // 3 seconds
|
|
67
70
|
#authRequests = {};
|
|
68
71
|
#metaStore = new MetadataStore();
|
|
69
72
|
// Map of providers currently injected in tabs
|
|
@@ -437,8 +440,27 @@ export default class State {
|
|
|
437
440
|
this.#notification = notification;
|
|
438
441
|
return true;
|
|
439
442
|
}
|
|
443
|
+
handleSignRequest(origin) {
|
|
444
|
+
const now = Date.now();
|
|
445
|
+
const lastTime = this.#lastRequestTimestamps.get(origin) || 0;
|
|
446
|
+
if (now - lastTime < this.#rateLimitInterval) {
|
|
447
|
+
throw new Error('Rate limit exceeded. Try again later.');
|
|
448
|
+
}
|
|
449
|
+
// If we're about to exceed max entries, evict the oldest
|
|
450
|
+
if (!this.#lastRequestTimestamps.has(origin) && this.#lastRequestTimestamps.size >= this.#maxEntries) {
|
|
451
|
+
const oldestKey = this.#lastRequestTimestamps.keys().next().value;
|
|
452
|
+
oldestKey && this.#lastRequestTimestamps.delete(oldestKey);
|
|
453
|
+
}
|
|
454
|
+
this.#lastRequestTimestamps.set(origin, now);
|
|
455
|
+
}
|
|
440
456
|
sign(url, request, account) {
|
|
441
457
|
const id = getId();
|
|
458
|
+
try {
|
|
459
|
+
this.handleSignRequest(url);
|
|
460
|
+
}
|
|
461
|
+
catch (error) {
|
|
462
|
+
return Promise.reject(error);
|
|
463
|
+
}
|
|
442
464
|
return new Promise((resolve, reject) => {
|
|
443
465
|
this.#signRequests[id] = {
|
|
444
466
|
...this.signComplete(id, resolve, reject),
|
|
@@ -20,6 +20,7 @@ export default class Tabs {
|
|
|
20
20
|
private rpcSubscribeConnected;
|
|
21
21
|
private rpcUnsubscribe;
|
|
22
22
|
private redirectPhishingLanding;
|
|
23
|
+
private parseUrl;
|
|
23
24
|
private redirectIfPhishing;
|
|
24
25
|
handle<TMessageType extends MessageTypes>(id: string, type: TMessageType, request: RequestTypes[TMessageType], url: string, port?: chrome.runtime.Port): Promise<ResponseTypes[keyof ResponseTypes]>;
|
|
25
26
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { combineLatest } from 'rxjs';
|
|
2
|
+
import { parse } from 'tldts';
|
|
2
3
|
import { checkIfDenied } from '@polkadot/phishing';
|
|
3
4
|
import { keyring } from '@polkadot/ui-keyring';
|
|
4
5
|
import { accounts as accountsObservable } from '@polkadot/ui-keyring/observable/accounts';
|
|
@@ -142,6 +143,19 @@ export default class Tabs {
|
|
|
142
143
|
.forEach((id) => withErrorLog(() => chrome.tabs.update(id, { url })));
|
|
143
144
|
});
|
|
144
145
|
}
|
|
146
|
+
parseUrl(rawUrl) {
|
|
147
|
+
let from = 'extension';
|
|
148
|
+
if (rawUrl) {
|
|
149
|
+
try {
|
|
150
|
+
const { hostname } = parse(rawUrl);
|
|
151
|
+
from = hostname || '<unknown>'; // Only use the hostname
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
from = '<unknown>';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return from;
|
|
158
|
+
}
|
|
145
159
|
async redirectIfPhishing(url) {
|
|
146
160
|
const isInDenyList = await checkIfDenied(url);
|
|
147
161
|
if (isInDenyList) {
|
|
@@ -152,7 +166,8 @@ export default class Tabs {
|
|
|
152
166
|
}
|
|
153
167
|
async handle(id, type, request, url, port) {
|
|
154
168
|
if (type === 'pub(phishing.redirectIfDenied)') {
|
|
155
|
-
|
|
169
|
+
const parsedUrl = this.parseUrl(url);
|
|
170
|
+
return this.redirectIfPhishing(parsedUrl);
|
|
156
171
|
}
|
|
157
172
|
if (type !== 'pub(authorize.tab)') {
|
|
158
173
|
this.#state.ensureUrlAuthorized(url);
|
|
@@ -90,6 +90,7 @@ export default class State {
|
|
|
90
90
|
rpcUnsubscribe(request: RequestRpcUnsubscribe, port: chrome.runtime.Port): Promise<boolean>;
|
|
91
91
|
saveMetadata(meta: MetadataDef): Promise<void>;
|
|
92
92
|
setNotification(notification: string): boolean;
|
|
93
|
+
private handleSignRequest;
|
|
93
94
|
sign(url: string, request: RequestSign, account: AccountJson): Promise<ResponseSigning>;
|
|
94
95
|
}
|
|
95
96
|
export {};
|
|
@@ -67,6 +67,9 @@ async function extractMetadata(store) {
|
|
|
67
67
|
}
|
|
68
68
|
class State {
|
|
69
69
|
#authUrls = new Map();
|
|
70
|
+
#lastRequestTimestamps = new Map();
|
|
71
|
+
#maxEntries = 10;
|
|
72
|
+
#rateLimitInterval = 3000; // 3 seconds
|
|
70
73
|
#authRequests = {};
|
|
71
74
|
#metaStore = new index_js_1.MetadataStore();
|
|
72
75
|
// Map of providers currently injected in tabs
|
|
@@ -440,8 +443,27 @@ class State {
|
|
|
440
443
|
this.#notification = notification;
|
|
441
444
|
return true;
|
|
442
445
|
}
|
|
446
|
+
handleSignRequest(origin) {
|
|
447
|
+
const now = Date.now();
|
|
448
|
+
const lastTime = this.#lastRequestTimestamps.get(origin) || 0;
|
|
449
|
+
if (now - lastTime < this.#rateLimitInterval) {
|
|
450
|
+
throw new Error('Rate limit exceeded. Try again later.');
|
|
451
|
+
}
|
|
452
|
+
// If we're about to exceed max entries, evict the oldest
|
|
453
|
+
if (!this.#lastRequestTimestamps.has(origin) && this.#lastRequestTimestamps.size >= this.#maxEntries) {
|
|
454
|
+
const oldestKey = this.#lastRequestTimestamps.keys().next().value;
|
|
455
|
+
oldestKey && this.#lastRequestTimestamps.delete(oldestKey);
|
|
456
|
+
}
|
|
457
|
+
this.#lastRequestTimestamps.set(origin, now);
|
|
458
|
+
}
|
|
443
459
|
sign(url, request, account) {
|
|
444
460
|
const id = (0, getId_js_1.getId)();
|
|
461
|
+
try {
|
|
462
|
+
this.handleSignRequest(url);
|
|
463
|
+
}
|
|
464
|
+
catch (error) {
|
|
465
|
+
return Promise.reject(error);
|
|
466
|
+
}
|
|
445
467
|
return new Promise((resolve, reject) => {
|
|
446
468
|
this.#signRequests[id] = {
|
|
447
469
|
...this.signComplete(id, resolve, reject),
|
|
@@ -20,6 +20,7 @@ export default class Tabs {
|
|
|
20
20
|
private rpcSubscribeConnected;
|
|
21
21
|
private rpcUnsubscribe;
|
|
22
22
|
private redirectPhishingLanding;
|
|
23
|
+
private parseUrl;
|
|
23
24
|
private redirectIfPhishing;
|
|
24
25
|
handle<TMessageType extends MessageTypes>(id: string, type: TMessageType, request: RequestTypes[TMessageType], url: string, port?: chrome.runtime.Port): Promise<ResponseTypes[keyof ResponseTypes]>;
|
|
25
26
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
|
+
const tldts_1 = require("tldts");
|
|
5
6
|
const phishing_1 = require("@polkadot/phishing");
|
|
6
7
|
const ui_keyring_1 = require("@polkadot/ui-keyring");
|
|
7
8
|
const accounts_1 = require("@polkadot/ui-keyring/observable/accounts");
|
|
@@ -145,6 +146,19 @@ class Tabs {
|
|
|
145
146
|
.forEach((id) => (0, helpers_js_1.withErrorLog)(() => chrome.tabs.update(id, { url })));
|
|
146
147
|
});
|
|
147
148
|
}
|
|
149
|
+
parseUrl(rawUrl) {
|
|
150
|
+
let from = 'extension';
|
|
151
|
+
if (rawUrl) {
|
|
152
|
+
try {
|
|
153
|
+
const { hostname } = (0, tldts_1.parse)(rawUrl);
|
|
154
|
+
from = hostname || '<unknown>'; // Only use the hostname
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
from = '<unknown>';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return from;
|
|
161
|
+
}
|
|
148
162
|
async redirectIfPhishing(url) {
|
|
149
163
|
const isInDenyList = await (0, phishing_1.checkIfDenied)(url);
|
|
150
164
|
if (isInDenyList) {
|
|
@@ -155,7 +169,8 @@ class Tabs {
|
|
|
155
169
|
}
|
|
156
170
|
async handle(id, type, request, url, port) {
|
|
157
171
|
if (type === 'pub(phishing.redirectIfDenied)') {
|
|
158
|
-
|
|
172
|
+
const parsedUrl = this.parseUrl(url);
|
|
173
|
+
return this.redirectIfPhishing(parsedUrl);
|
|
159
174
|
}
|
|
160
175
|
if (type !== 'pub(authorize.tab)') {
|
|
161
176
|
this.#state.ensureUrlAuthorized(url);
|
package/cjs/packageInfo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.packageInfo = void 0;
|
|
4
|
-
exports.packageInfo = { name: '@polkadot/extension-base', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '0.
|
|
4
|
+
exports.packageInfo = { name: '@polkadot/extension-base', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '0.61.1' };
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"./cjs/packageDetect.js"
|
|
19
19
|
],
|
|
20
20
|
"type": "module",
|
|
21
|
-
"version": "0.
|
|
21
|
+
"version": "0.61.1",
|
|
22
22
|
"main": "./cjs/index.js",
|
|
23
23
|
"module": "./index.js",
|
|
24
24
|
"types": "./index.d.ts",
|
|
@@ -480,9 +480,9 @@
|
|
|
480
480
|
},
|
|
481
481
|
"dependencies": {
|
|
482
482
|
"@polkadot/api": "^16.2.2",
|
|
483
|
-
"@polkadot/extension-chains": "0.
|
|
484
|
-
"@polkadot/extension-dapp": "0.
|
|
485
|
-
"@polkadot/extension-inject": "0.
|
|
483
|
+
"@polkadot/extension-chains": "0.61.1",
|
|
484
|
+
"@polkadot/extension-dapp": "0.61.1",
|
|
485
|
+
"@polkadot/extension-inject": "0.61.1",
|
|
486
486
|
"@polkadot/keyring": "^13.5.2",
|
|
487
487
|
"@polkadot/networks": "^13.5.2",
|
|
488
488
|
"@polkadot/phishing": "^0.25.13",
|
|
@@ -494,6 +494,7 @@
|
|
|
494
494
|
"@polkadot/util-crypto": "^13.5.2",
|
|
495
495
|
"eventemitter3": "^5.0.1",
|
|
496
496
|
"rxjs": "^7.8.1",
|
|
497
|
+
"tldts": "^7.0.8",
|
|
497
498
|
"tslib": "^2.8.1"
|
|
498
499
|
}
|
|
499
500
|
}
|
package/packageInfo.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const packageInfo = { name: '@polkadot/extension-base', path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '0.
|
|
1
|
+
export const packageInfo = { name: '@polkadot/extension-base', path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '0.61.1' };
|