Skip to content

Commit 52131df

Browse files
Copilot0xrinegade
andcommitted
Fix runtime errors: wallet extension conflicts, null property access, and CSP violations
Co-authored-by: 0xrinegade <[email protected]>
1 parent 97fa68a commit 52131df

File tree

5 files changed

+423
-19
lines changed

5 files changed

+423
-19
lines changed

public/buffer-polyfill.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,80 @@
183183
var global = window;
184184
}
185185

186+
// Add defensive handling for wallet extension conflicts
187+
(function() {
188+
try {
189+
// Store reference to any existing ethereum provider
190+
const existingEthereum = window.ethereum;
191+
192+
// Add safe ethereum property handling to prevent conflicts
193+
if (!window.ethereumHandlersInitialized) {
194+
window.ethereumHandlersInitialized = true;
195+
196+
// Create a non-conflicting ethereum property wrapper
197+
Object.defineProperty(window, '_svmseekEthereumSafe', {
198+
value: existingEthereum,
199+
writable: false,
200+
configurable: false
201+
});
202+
203+
// Override Object.defineProperty to handle ethereum property conflicts
204+
const originalDefineProperty = Object.defineProperty;
205+
Object.defineProperty = function(obj, prop, descriptor) {
206+
if (obj === window && prop === 'ethereum') {
207+
try {
208+
// If ethereum already exists and is non-configurable, skip redefinition
209+
const existingDescriptor = Object.getOwnPropertyDescriptor(window, 'ethereum');
210+
if (existingDescriptor && !existingDescriptor.configurable) {
211+
console.warn('SVMSeek: Skipping ethereum property redefinition to prevent conflicts');
212+
return obj;
213+
}
214+
215+
// Allow the definition but catch any errors
216+
return originalDefineProperty.call(this, obj, prop, descriptor);
217+
} catch (error) {
218+
console.warn('SVMSeek: Prevented ethereum property conflict:', error.message);
219+
return obj;
220+
}
221+
}
222+
return originalDefineProperty.call(this, obj, prop, descriptor);
223+
};
224+
225+
console.log('SVMSeek: Ethereum property conflict protection enabled');
226+
}
227+
} catch (error) {
228+
console.warn('SVMSeek: Failed to setup ethereum conflict protection:', error);
229+
}
230+
})();
231+
232+
// Add protection against custom element conflicts
233+
(function() {
234+
try {
235+
if (!window.customElementConflictProtection) {
236+
window.customElementConflictProtection = true;
237+
238+
// Override customElements.define to prevent conflicts
239+
const originalDefine = window.customElements.define;
240+
window.customElements.define = function(name, constructor, options) {
241+
try {
242+
// Check if element is already defined
243+
if (window.customElements.get(name)) {
244+
console.warn('SVMSeek: Custom element already defined, skipping:', name);
245+
return;
246+
}
247+
return originalDefine.call(this, name, constructor, options);
248+
} catch (error) {
249+
console.warn('SVMSeek: Custom element definition conflict prevented for:', name, error.message);
250+
}
251+
};
252+
253+
console.log('SVMSeek: Custom element conflict protection enabled');
254+
}
255+
} catch (error) {
256+
console.warn('SVMSeek: Failed to setup custom element protection:', error);
257+
}
258+
})();
259+
186260
// Add additional crypto polyfills that might be needed
187261
if (!window.crypto && !window.msCrypto) {
188262
console.warn('WebCrypto API not available');

public/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
<meta name="theme-color" content="#000000" />
8+
<!-- Enhanced Content Security Policy for better security and iframe compatibility -->
9+
<meta http-equiv="Content-Security-Policy" content="
10+
default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob: https:;
11+
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com https://fonts.gstatic.com https://www.googletagmanager.com https://cdn.jsdelivr.net;
12+
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://fonts.gstatic.com;
13+
font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com;
14+
img-src 'self' data: blob: https:;
15+
connect-src 'self' https: wss: ws:;
16+
frame-src 'self' https: blob: data:;
17+
child-src 'self' https: blob: data:;
18+
worker-src 'self' blob:;
19+
media-src 'self' data: blob: https:;
20+
object-src 'none';
21+
base-uri 'self';
22+
form-action 'self';
23+
">
824
<meta
925
name="description"
1026
content="Wallet™ with support for SPL tokens."

src/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// CRITICAL: Import complete polyfills FIRST before any other modules
22
import './polyfills/index.js';
33

4+
// Import global error handler early to catch initialization errors
5+
import './utils/globalErrorHandler';
6+
47
// Import React and other modules AFTER polyfills
58
import React from 'react';
69
import { createRoot } from 'react-dom/client';

src/services/WalletInjectionService.ts

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,30 @@ export class WalletInjectionService {
134134
*/
135135
private setupMessageListener(): void {
136136
window.addEventListener('message', (event) => {
137-
if (!this.iframe || event.source !== this.iframe.contentWindow) {
138-
return;
139-
}
137+
try {
138+
if (!this.iframe || event.source !== this.iframe.contentWindow) {
139+
return;
140+
}
140141

141-
const { type, id, method, params } = event.data;
142-
143-
if (type === 'WALLET_REQUEST') {
144-
this.handleWalletRequest(id, method, params);
142+
// Safely check if event.data exists and has the expected structure
143+
if (!event.data || typeof event.data !== 'object') {
144+
logWarn('WalletInjectionService: Received invalid message data', event.data);
145+
return;
146+
}
147+
148+
const { type, id, method, params } = event.data;
149+
150+
// Additional null/undefined checks
151+
if (!type || typeof type !== 'string') {
152+
logWarn('WalletInjectionService: Received message without valid type', event.data);
153+
return;
154+
}
155+
156+
if (type === 'WALLET_REQUEST') {
157+
this.handleWalletRequest(id, method, params);
158+
}
159+
} catch (error) {
160+
logError('WalletInjectionService: Error processing message:', error, event.data);
145161
}
146162
});
147163
}
@@ -274,18 +290,34 @@ export class WalletInjectionService {
274290
275291
// Handle responses from parent window
276292
window.addEventListener('message', (event) => {
277-
if (event.source !== window.parent) return;
278-
279-
const { type, id, result, error } = event.data;
280-
281-
if (type === 'WALLET_RESPONSE' && pendingRequests.has(id)) {
282-
const { resolve } = pendingRequests.get(id);
283-
pendingRequests.delete(id);
284-
resolve(result);
285-
} else if (type === 'WALLET_ERROR' && pendingRequests.has(id)) {
286-
const { reject } = pendingRequests.get(id);
287-
pendingRequests.delete(id);
288-
reject(new Error(error));
293+
try {
294+
if (event.source !== window.parent) return;
295+
296+
// Safely check if event.data exists
297+
if (!event.data || typeof event.data !== 'object') {
298+
console.warn('SVMSeek: Received invalid message data in iframe', event.data);
299+
return;
300+
}
301+
302+
const { type, id, result, error } = event.data;
303+
304+
// Check if type is valid
305+
if (!type || typeof type !== 'string') {
306+
console.warn('SVMSeek: Received message without valid type in iframe', event.data);
307+
return;
308+
}
309+
310+
if (type === 'WALLET_RESPONSE' && id && pendingRequests.has(id)) {
311+
const { resolve } = pendingRequests.get(id);
312+
pendingRequests.delete(id);
313+
resolve(result);
314+
} else if (type === 'WALLET_ERROR' && id && pendingRequests.has(id)) {
315+
const { reject } = pendingRequests.get(id);
316+
pendingRequests.delete(id);
317+
reject(new Error(error || 'Unknown wallet error'));
318+
}
319+
} catch (err) {
320+
console.error('SVMSeek: Error processing message in iframe:', err, event.data);
289321
}
290322
});
291323

0 commit comments

Comments
 (0)