Skip to content

Commit 2b45987

Browse files
Copilot0xrinegade
andcommitted
Address code review feedback: security, fragments, error handling, and manifest upgrades
Co-authored-by: 0xrinegade <[email protected]>
1 parent 8ec9444 commit 2b45987

File tree

10 files changed

+55
-41
lines changed

10 files changed

+55
-41
lines changed

extension/extension-build-info.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
SVMSeek Wallet Browser Extensions
22
=================================
3-
Build Date: Mon Aug 11 15:44:03 UTC 2025
3+
Build Date: Mon Aug 11 18:33:56 UTC 2025
44
Extensions Built: Chrome, Firefox, Safari, Edge
55

66
Extension Details:
77
- chrome: 3.3M (Manifest v3)
8-
- firefox: 3.3M (Manifest v2)
9-
- safari: 3.3M (Manifest v2)
8+
- firefox: 3.3M (Manifest v3)
9+
- safari: 3.3M (Manifest v3)
1010
- edge: 3.3M (Manifest v3)
1111

1212
Distribution:

extension/firefox/manifest.json

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"manifest_version": 2,
2+
"manifest_version": 3,
33
"short_name": "SVMSeek Wallet",
44
"name": "SVMSeek SPL Token Wallet",
55
"description": "Secure Solana wallet for SPL tokens and DeFi applications",
@@ -13,13 +13,14 @@
1313
"permissions": [
1414
"activeTab",
1515
"storage",
16-
"tabs",
16+
"tabs"
17+
],
18+
"host_permissions": [
1719
"https://*.solana.com/*",
1820
"https://*.svmseek.com/*"
1921
],
2022
"background": {
21-
"scripts": ["background.js"],
22-
"persistent": false
23+
"service_worker": "background.js"
2324
},
2425
"content_scripts": [
2526
{
@@ -28,7 +29,7 @@
2829
"run_at": "document_start"
2930
}
3031
],
31-
"browser_action": {
32+
"action": {
3233
"default_popup": "index.html",
3334
"default_title": "SVMSeek Wallet",
3435
"default_icon": {
@@ -39,9 +40,12 @@
3940
}
4041
},
4142
"web_accessible_resources": [
42-
"script.js"
43+
{
44+
"resources": ["script.js"],
45+
"matches": ["<all_urls>"]
46+
}
4347
],
44-
"applications": {
48+
"browser_specific_settings": {
4549
"gecko": {
4650
"id": "{[email protected]}",
4751
"strict_min_version": "109.0"

extension/safari/manifest.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"manifest_version": 2,
2+
"manifest_version": 3,
33
"short_name": "SVMSeek Wallet",
44
"name": "SVMSeek SPL Token Wallet",
55
"description": "Secure Solana wallet for SPL tokens and DeFi applications",
@@ -13,13 +13,14 @@
1313
"permissions": [
1414
"activeTab",
1515
"storage",
16-
"tabs",
16+
"tabs"
17+
],
18+
"host_permissions": [
1719
"https://*.solana.com/*",
1820
"https://*.svmseek.com/*"
1921
],
2022
"background": {
21-
"scripts": ["background.js"],
22-
"persistent": false
23+
"service_worker": "background.js"
2324
},
2425
"content_scripts": [
2526
{
@@ -28,7 +29,7 @@
2829
"run_at": "document_start"
2930
}
3031
],
31-
"browser_action": {
32+
"action": {
3233
"default_popup": "index.html",
3334
"default_title": "SVMSeek Wallet",
3435
"default_icon": {
@@ -39,6 +40,9 @@
3940
}
4041
},
4142
"web_accessible_resources": [
42-
"script.js"
43+
{
44+
"resources": ["script.js"],
45+
"matches": ["<all_urls>"]
46+
}
4347
]
4448
}

extension/src/contentscript.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ scriptTag.src = chrome.runtime.getURL('script.js');
55
container.insertBefore(scriptTag, container.children[0]);
66
container.removeChild(scriptTag);
77

8-
window.addEventListener('ccai_injected_script_message', (event) => {
8+
// Store event handler reference for cleanup
9+
const messageHandler = (event) => {
910
chrome.runtime.sendMessage(
1011
{
1112
channel: 'ccai_contentscript_background_channel',
@@ -21,4 +22,11 @@ window.addEventListener('ccai_injected_script_message', (event) => {
2122
);
2223
},
2324
);
25+
};
26+
27+
window.addEventListener('ccai_injected_script_message', messageHandler);
28+
29+
// Cleanup event listener when extension is unloaded
30+
window.addEventListener('beforeunload', () => {
31+
window.removeEventListener('ccai_injected_script_message', messageHandler);
2432
});

src/components/AddAccountDialog.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import FormGroup from '@mui/material/FormGroup';
99
import Switch from '@mui/material/Switch';
1010
import { Account } from '@solana/web3.js';
1111
import DialogForm from '../pages/Wallet/components/DialogForm';
12+
import { devLog } from '../utils/logger';
1213

1314
export default function AddAccountDialog({ open, onAdd, onClose }) {
1415
const [name, setName] = useState('');
@@ -91,7 +92,8 @@ function decodeAccount(privateKey) {
9192
try {
9293
const a = new Account(JSON.parse(privateKey));
9394
return a;
94-
} catch (_) {
95+
} catch (error) {
96+
devLog('Failed to decode private key:', error.message);
9597
return undefined;
9698
}
9799
}

src/components/MergeAccountsDialog.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
import { sleep } from '../utils/utils';
3131
import { useTokenInfosMap, getTokenInfo } from '../utils/tokens/names';
3232

33+
const MERGE_CONFIRMATION_TEXT = 'merge';
34+
3335
export default function MergeAccountsDialog({ open, onClose }) {
3436
const theme = useTheme();
3537
const [publicKeys] = useWalletPublicKeys();
@@ -154,7 +156,7 @@ export default function MergeAccountsDialog({ open, onClose }) {
154156
setMergeCheck('');
155157
onClose();
156158
};
157-
const disabled = mergeCheck.toLowerCase() !== 'merge';
159+
const disabled = mergeCheck.toLowerCase() !== MERGE_CONFIRMATION_TEXT;
158160

159161
return (
160162
<DialogForm
@@ -239,7 +241,7 @@ export default function MergeAccountsDialog({ open, onClose }) {
239241
margin="normal"
240242
value={mergeCheck}
241243
onChange={(e) => setMergeCheck(e.target.value.trim())}
242-
placeholder={'Type "merge" to confirm'}
244+
placeholder={`Type "${MERGE_CONFIRMATION_TEXT}" to confirm`}
243245
/>
244246
</RowContainer>
245247
<RowContainer padding={'1rem 0'} justify={'space-between'}>

src/components/instructions/TokenInstruction.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default function TokenInstruction({ instruction, onOpenAddress }) {
4141
};
4242

4343
return (
44-
<>
44+
<React.Fragment>
4545
<Title
4646
variant="subtitle1"
4747
style={{ fontWeight: 'bold', fontSize: '1.6rem' }}
@@ -66,6 +66,6 @@ export default function TokenInstruction({ instruction, onOpenAddress }) {
6666
/>
6767
);
6868
})}
69-
</>
69+
</React.Fragment>
7070
);
7171
}

src/components/instructions/UnknownInstruction.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import LabelValue from './LabelValue';
44

55
export default function UnknownInstruction({ instruction, onOpenAddress }) {
66
return (
7-
<>
7+
<React.Fragment>
88
<Title variant="subtitle1" style={{ fontWeight: 'bold' }} gutterBottom>
99
Unknown instruction:
1010
</Title>
@@ -19,7 +19,7 @@ export default function UnknownInstruction({ instruction, onOpenAddress }) {
1919
{instruction.accountMetas &&
2020
instruction.accountMetas.map((accountMeta, index) => {
2121
return (
22-
<>
22+
<React.Fragment key={index}>
2323
<LabelValue
2424
key={index + ''}
2525
label={'Account #' + (index + 1)}
@@ -30,12 +30,12 @@ export default function UnknownInstruction({ instruction, onOpenAddress }) {
3030
<Title gutterBottom>
3131
Writable: {accountMeta.isWritable.toString()}
3232
</Title>
33-
</>
33+
</React.Fragment>
3434
);
3535
})}
3636
<Title style={{ wordBreak: 'break-all' }}>
3737
Data: {instruction.rawData}
3838
</Title>
39-
</>
39+
</React.Fragment>
4040
);
4141
}

src/utils/swap/eth.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useCallAsync } from '../notifications';
66
import { VioletButton } from '../../pages/commonStyles';
77
import { useTheme } from '@mui/material';
88
import { isExtension } from '../utils';
9+
import { devLog } from '../logger';
910

1011
const web3 = new Web3(window.ethereum);
1112
// Change to use estimated gas limit
@@ -198,6 +199,7 @@ export async function withdrawEth(from, withdrawal, callAsync) {
198199
try {
199200
await method.estimateGas();
200201
} catch (e) {
202+
devLog('Gas estimation failed for withdrawal:', e.message);
201203
return;
202204
}
203205
pendingNonces.add(nonce);

src/utils/walletProvider/localStorage.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,8 @@ export function getAccountFromSeed(
2929
return new Account(accountData.secretKey);
3030
} catch (error) {
3131
logError('getAccountFromSeed failed:', error);
32-
// Return a fallback account with a deterministic key based on wallet index
33-
const fallbackSeed = new Uint8Array(32);
34-
fallbackSeed[0] = (walletIndex || 0) % 256;
35-
const fallbackKeyPair = nacl.sign.keyPair.fromSeed(fallbackSeed);
36-
return new Account(fallbackKeyPair.secretKey);
32+
// Fail securely instead of using weak fallback keys
33+
throw new Error('Unable to generate secure account keys. Please unlock wallet again.');
3734
}
3835
}
3936

@@ -61,9 +58,8 @@ export class LocalStorageWalletProvider {
6158
if (seed) {
6259
seedBuffer = Buffer.from(seed, 'hex');
6360
} else {
64-
// Fallback seed if none available
65-
seedBuffer = Buffer.alloc(32);
66-
logWarn('Using fallback seed for address listing');
61+
// Fail securely if no seed available instead of using weak fallback
62+
throw new Error('No seed available for secure key generation');
6763
}
6864

6965
return [...Array(walletCount).keys()].map((walletIndex) => {
@@ -79,17 +75,13 @@ export class LocalStorageWalletProvider {
7975
`Failed to generate address for wallet ${walletIndex}:`,
8076
error,
8177
);
82-
// Return a fallback address structure
83-
return {
84-
index: walletIndex,
85-
address: null,
86-
name: `Wallet ${walletIndex} (Error)`,
87-
};
78+
// Return error structure instead of weak fallback
79+
throw new Error(`Unable to generate secure address for wallet ${walletIndex}`);
8880
}
8981
});
9082
} catch (error) {
9183
logError('Failed to list addresses:', error);
92-
return [];
84+
throw new Error('Unable to list addresses securely. Please unlock wallet again.');
9385
}
9486
};
9587

0 commit comments

Comments
 (0)