@shadow-corp/nearconnect 1.0.0
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/README.md +546 -0
- package/build/InjectedWallet.d.ts +22 -0
- package/build/InjectedWallet.js +58 -0
- package/build/InjectedWallet.js.map +1 -0
- package/build/NearConnector.d.ts +151 -0
- package/build/NearConnector.js +536 -0
- package/build/NearConnector.js.map +1 -0
- package/build/ParentFrameWallet.d.ts +22 -0
- package/build/ParentFrameWallet.js +66 -0
- package/build/ParentFrameWallet.js.map +1 -0
- package/build/SandboxedWallet/code.d.ts +7 -0
- package/build/SandboxedWallet/code.js +324 -0
- package/build/SandboxedWallet/code.js.map +1 -0
- package/build/SandboxedWallet/executor.d.ts +23 -0
- package/build/SandboxedWallet/executor.js +338 -0
- package/build/SandboxedWallet/executor.js.map +1 -0
- package/build/SandboxedWallet/iframe.d.ts +18 -0
- package/build/SandboxedWallet/iframe.js +78 -0
- package/build/SandboxedWallet/iframe.js.map +1 -0
- package/build/SandboxedWallet/index.d.ts +24 -0
- package/build/SandboxedWallet/index.js +54 -0
- package/build/SandboxedWallet/index.js.map +1 -0
- package/build/actions/index.d.ts +3 -0
- package/build/actions/index.js +105 -0
- package/build/actions/index.js.map +1 -0
- package/build/actions/types.d.ts +76 -0
- package/build/actions/types.js +3 -0
- package/build/actions/types.js.map +1 -0
- package/build/connection/health.d.ts +213 -0
- package/build/connection/health.js +391 -0
- package/build/connection/health.js.map +1 -0
- package/build/connection/index.d.ts +4 -0
- package/build/connection/index.js +48 -0
- package/build/connection/index.js.map +1 -0
- package/build/connection/reconnect.d.ts +261 -0
- package/build/connection/reconnect.js +454 -0
- package/build/connection/reconnect.js.map +1 -0
- package/build/connection/retry.d.ts +187 -0
- package/build/connection/retry.js +427 -0
- package/build/connection/retry.js.map +1 -0
- package/build/connection/state.d.ts +222 -0
- package/build/connection/state.js +431 -0
- package/build/connection/state.js.map +1 -0
- package/build/errors.d.ts +177 -0
- package/build/errors.js +546 -0
- package/build/errors.js.map +1 -0
- package/build/hardware/errors.d.ts +36 -0
- package/build/hardware/errors.js +127 -0
- package/build/hardware/errors.js.map +1 -0
- package/build/hardware/index.d.ts +7 -0
- package/build/hardware/index.js +39 -0
- package/build/hardware/index.js.map +1 -0
- package/build/hardware/near-app.d.ts +95 -0
- package/build/hardware/near-app.js +291 -0
- package/build/hardware/near-app.js.map +1 -0
- package/build/hardware/transport.d.ts +94 -0
- package/build/hardware/transport.js +267 -0
- package/build/hardware/transport.js.map +1 -0
- package/build/hardware/types.d.ts +98 -0
- package/build/hardware/types.js +72 -0
- package/build/hardware/types.js.map +1 -0
- package/build/helpers/analytics.d.ts +191 -0
- package/build/helpers/analytics.js +304 -0
- package/build/helpers/analytics.js.map +1 -0
- package/build/helpers/base58.d.ts +6 -0
- package/build/helpers/base58.js +47 -0
- package/build/helpers/base58.js.map +1 -0
- package/build/helpers/events.d.ts +42 -0
- package/build/helpers/events.js +68 -0
- package/build/helpers/events.js.map +1 -0
- package/build/helpers/html.d.ts +8 -0
- package/build/helpers/html.js +30 -0
- package/build/helpers/html.js.map +1 -0
- package/build/helpers/indexdb.d.ts +14 -0
- package/build/helpers/indexdb.js +166 -0
- package/build/helpers/indexdb.js.map +1 -0
- package/build/helpers/manifest.d.ts +147 -0
- package/build/helpers/manifest.js +329 -0
- package/build/helpers/manifest.js.map +1 -0
- package/build/helpers/queue.d.ts +11 -0
- package/build/helpers/queue.js +48 -0
- package/build/helpers/queue.js.map +1 -0
- package/build/helpers/session.d.ts +119 -0
- package/build/helpers/session.js +289 -0
- package/build/helpers/session.js.map +1 -0
- package/build/helpers/simulation.d.ts +128 -0
- package/build/helpers/simulation.js +441 -0
- package/build/helpers/simulation.js.map +1 -0
- package/build/helpers/storage.d.ts +58 -0
- package/build/helpers/storage.js +190 -0
- package/build/helpers/storage.js.map +1 -0
- package/build/helpers/trust.d.ts +157 -0
- package/build/helpers/trust.js +340 -0
- package/build/helpers/trust.js.map +1 -0
- package/build/helpers/url.d.ts +1 -0
- package/build/helpers/url.js +13 -0
- package/build/helpers/url.js.map +1 -0
- package/build/helpers/uuid.d.ts +1 -0
- package/build/helpers/uuid.js +14 -0
- package/build/helpers/uuid.js.map +1 -0
- package/build/index.d.ts +21 -0
- package/build/index.js +167 -0
- package/build/index.js.map +1 -0
- package/build/popups/IframeWalletPopup.d.ts +16 -0
- package/build/popups/IframeWalletPopup.js +38 -0
- package/build/popups/IframeWalletPopup.js.map +1 -0
- package/build/popups/NearWalletsPopup.d.ts +25 -0
- package/build/popups/NearWalletsPopup.js +153 -0
- package/build/popups/NearWalletsPopup.js.map +1 -0
- package/build/popups/Popup.d.ts +22 -0
- package/build/popups/Popup.js +94 -0
- package/build/popups/Popup.js.map +1 -0
- package/build/popups/styles.d.ts +1 -0
- package/build/popups/styles.js +257 -0
- package/build/popups/styles.js.map +1 -0
- package/build/security/audit-log.d.ts +123 -0
- package/build/security/audit-log.js +268 -0
- package/build/security/audit-log.js.map +1 -0
- package/build/security/csp.d.ts +68 -0
- package/build/security/csp.js +328 -0
- package/build/security/csp.js.map +1 -0
- package/build/security/index.d.ts +10 -0
- package/build/security/index.js +42 -0
- package/build/security/index.js.map +1 -0
- package/build/security/origin-guard.d.ts +90 -0
- package/build/security/origin-guard.js +244 -0
- package/build/security/origin-guard.js.map +1 -0
- package/build/security/rate-limiter.d.ts +84 -0
- package/build/security/rate-limiter.js +212 -0
- package/build/security/rate-limiter.js.map +1 -0
- package/build/security/secure-storage.d.ts +77 -0
- package/build/security/secure-storage.js +242 -0
- package/build/security/secure-storage.js.map +1 -0
- package/build/security/transaction-guard.d.ts +71 -0
- package/build/security/transaction-guard.js +239 -0
- package/build/security/transaction-guard.js.map +1 -0
- package/build/types.d.ts +508 -0
- package/build/types.js +3 -0
- package/build/types.js.map +1 -0
- package/build/ui/AccountSwitcherModal.d.ts +53 -0
- package/build/ui/AccountSwitcherModal.js +239 -0
- package/build/ui/AccountSwitcherModal.js.map +1 -0
- package/build/ui/Modal.d.ts +84 -0
- package/build/ui/Modal.js +278 -0
- package/build/ui/Modal.js.map +1 -0
- package/build/ui/TransactionModal.d.ts +84 -0
- package/build/ui/TransactionModal.js +406 -0
- package/build/ui/TransactionModal.js.map +1 -0
- package/build/ui/WalletSelectorModal.d.ts +97 -0
- package/build/ui/WalletSelectorModal.js +481 -0
- package/build/ui/WalletSelectorModal.js.map +1 -0
- package/build/ui/icons.d.ts +19 -0
- package/build/ui/icons.js +65 -0
- package/build/ui/icons.js.map +1 -0
- package/build/ui/index.d.ts +10 -0
- package/build/ui/index.js +31 -0
- package/build/ui/index.js.map +1 -0
- package/build/ui/styles.d.ts +5 -0
- package/build/ui/styles.js +973 -0
- package/build/ui/styles.js.map +1 -0
- package/build/ui/theme.d.ts +133 -0
- package/build/ui/theme.js +204 -0
- package/build/ui/theme.js.map +1 -0
- package/build/wallets/external/index.d.ts +4 -0
- package/build/wallets/external/index.js +9 -0
- package/build/wallets/external/index.js.map +1 -0
- package/build/wallets/external/manager.d.ts +152 -0
- package/build/wallets/external/manager.js +586 -0
- package/build/wallets/external/manager.js.map +1 -0
- package/build/wallets/privileged/index.d.ts +5 -0
- package/build/wallets/privileged/index.js +12 -0
- package/build/wallets/privileged/index.js.map +1 -0
- package/build/wallets/privileged/ledger.d.ts +132 -0
- package/build/wallets/privileged/ledger.js +563 -0
- package/build/wallets/privileged/ledger.js.map +1 -0
- package/build/wallets/privileged/manager.d.ts +54 -0
- package/build/wallets/privileged/manager.js +174 -0
- package/build/wallets/privileged/manager.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audit Logging Layer
|
|
4
|
+
* Tracks all wallet actions for investigation and compliance
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.AuditLog = void 0;
|
|
8
|
+
exports.createAuditLog = createAuditLog;
|
|
9
|
+
class AuditLog {
|
|
10
|
+
events = [];
|
|
11
|
+
config;
|
|
12
|
+
sessionId;
|
|
13
|
+
remoteQueue = [];
|
|
14
|
+
flushTimeout = null;
|
|
15
|
+
constructor(config = { enabled: true }) {
|
|
16
|
+
this.config = {
|
|
17
|
+
maxEvents: 1000,
|
|
18
|
+
consoleLog: false,
|
|
19
|
+
persist: false,
|
|
20
|
+
...config,
|
|
21
|
+
};
|
|
22
|
+
this.sessionId = crypto.randomUUID();
|
|
23
|
+
// Load persisted events
|
|
24
|
+
if (this.config.persist) {
|
|
25
|
+
this.loadPersistedEvents();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Log an audit event
|
|
30
|
+
*/
|
|
31
|
+
log(type, data) {
|
|
32
|
+
if (!this.config.enabled)
|
|
33
|
+
return null;
|
|
34
|
+
// Filter by event types if configured
|
|
35
|
+
if (this.config.eventTypes && !this.config.eventTypes.includes(type)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const event = {
|
|
39
|
+
id: crypto.randomUUID(),
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
type,
|
|
42
|
+
sessionId: this.sessionId,
|
|
43
|
+
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,
|
|
44
|
+
...data,
|
|
45
|
+
};
|
|
46
|
+
// Add to memory
|
|
47
|
+
this.events.push(event);
|
|
48
|
+
// Trim old events
|
|
49
|
+
if (this.events.length > (this.config.maxEvents || 1000)) {
|
|
50
|
+
this.events = this.events.slice(-(this.config.maxEvents || 1000) / 2);
|
|
51
|
+
}
|
|
52
|
+
// Callback
|
|
53
|
+
this.config.onEvent?.(event);
|
|
54
|
+
// Console log security events
|
|
55
|
+
if (this.config.consoleLog || this.isSecurityEvent(type)) {
|
|
56
|
+
this.consoleLogEvent(event);
|
|
57
|
+
}
|
|
58
|
+
// Persist if enabled
|
|
59
|
+
if (this.config.persist) {
|
|
60
|
+
this.persistEvents();
|
|
61
|
+
}
|
|
62
|
+
// Queue for remote if configured
|
|
63
|
+
if (this.config.remoteEndpoint) {
|
|
64
|
+
this.queueRemote(event);
|
|
65
|
+
}
|
|
66
|
+
return event;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Log a security violation
|
|
70
|
+
*/
|
|
71
|
+
logSecurityViolation(message, data, risk = 'high') {
|
|
72
|
+
return this.log('security:violation', {
|
|
73
|
+
data: { message, ...data },
|
|
74
|
+
risk,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Log a security warning
|
|
79
|
+
*/
|
|
80
|
+
logSecurityWarning(message, data) {
|
|
81
|
+
return this.log('security:warning', {
|
|
82
|
+
data: { message, ...data },
|
|
83
|
+
risk: 'medium',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Log a transaction
|
|
88
|
+
*/
|
|
89
|
+
logTransaction(type, txData) {
|
|
90
|
+
return this.log(type, {
|
|
91
|
+
walletId: txData.walletId,
|
|
92
|
+
accountId: txData.accountId,
|
|
93
|
+
data: {
|
|
94
|
+
receiverId: txData.receiverId,
|
|
95
|
+
hash: txData.hash,
|
|
96
|
+
error: txData.error,
|
|
97
|
+
},
|
|
98
|
+
risk: txData.risk,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get events with optional filtering
|
|
103
|
+
*/
|
|
104
|
+
getEvents(filter) {
|
|
105
|
+
let events = [...this.events];
|
|
106
|
+
if (filter?.type) {
|
|
107
|
+
const types = Array.isArray(filter.type) ? filter.type : [filter.type];
|
|
108
|
+
events = events.filter(e => types.includes(e.type));
|
|
109
|
+
}
|
|
110
|
+
if (filter?.since) {
|
|
111
|
+
events = events.filter(e => e.timestamp >= filter.since);
|
|
112
|
+
}
|
|
113
|
+
if (filter?.until) {
|
|
114
|
+
events = events.filter(e => e.timestamp <= filter.until);
|
|
115
|
+
}
|
|
116
|
+
if (filter?.walletId) {
|
|
117
|
+
events = events.filter(e => e.walletId === filter.walletId);
|
|
118
|
+
}
|
|
119
|
+
if (filter?.accountId) {
|
|
120
|
+
events = events.filter(e => e.accountId === filter.accountId);
|
|
121
|
+
}
|
|
122
|
+
if (filter?.risk) {
|
|
123
|
+
const risks = Array.isArray(filter.risk) ? filter.risk : [filter.risk];
|
|
124
|
+
events = events.filter(e => e.risk && risks.includes(e.risk));
|
|
125
|
+
}
|
|
126
|
+
if (filter?.limit) {
|
|
127
|
+
events = events.slice(-filter.limit);
|
|
128
|
+
}
|
|
129
|
+
return events;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get security-related events
|
|
133
|
+
*/
|
|
134
|
+
getSecurityEvents() {
|
|
135
|
+
return this.getEvents({
|
|
136
|
+
type: ['security:violation', 'security:warning', 'tx:blocked', 'rate:limited'],
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get events for a specific session
|
|
141
|
+
*/
|
|
142
|
+
getSessionEvents(sessionId) {
|
|
143
|
+
const sid = sessionId || this.sessionId;
|
|
144
|
+
return this.events.filter(e => e.sessionId === sid);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Export events as JSON
|
|
148
|
+
*/
|
|
149
|
+
export(filter) {
|
|
150
|
+
const events = filter ? this.getEvents(filter) : this.events;
|
|
151
|
+
return JSON.stringify(events, null, 2);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Export events as CSV
|
|
155
|
+
*/
|
|
156
|
+
exportCsv(filter) {
|
|
157
|
+
const events = filter ? this.getEvents(filter) : this.events;
|
|
158
|
+
const headers = ['id', 'timestamp', 'type', 'walletId', 'accountId', 'risk', 'data'];
|
|
159
|
+
const rows = events.map(e => [
|
|
160
|
+
e.id,
|
|
161
|
+
new Date(e.timestamp).toISOString(),
|
|
162
|
+
e.type,
|
|
163
|
+
e.walletId || '',
|
|
164
|
+
e.accountId || '',
|
|
165
|
+
e.risk || '',
|
|
166
|
+
JSON.stringify(e.data || {}),
|
|
167
|
+
]);
|
|
168
|
+
return [headers.join(','), ...rows.map(r => r.map(c => `"${c}"`).join(','))].join('\n');
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Clear all events
|
|
172
|
+
*/
|
|
173
|
+
clear() {
|
|
174
|
+
this.events = [];
|
|
175
|
+
if (this.config.persist) {
|
|
176
|
+
localStorage.removeItem('near-connect:audit-log');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get current session ID
|
|
181
|
+
*/
|
|
182
|
+
getSessionId() {
|
|
183
|
+
return this.sessionId;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Flush remote queue immediately
|
|
187
|
+
*/
|
|
188
|
+
async flushRemote() {
|
|
189
|
+
if (!this.config.remoteEndpoint || this.remoteQueue.length === 0)
|
|
190
|
+
return;
|
|
191
|
+
const events = [...this.remoteQueue];
|
|
192
|
+
this.remoteQueue = [];
|
|
193
|
+
try {
|
|
194
|
+
await fetch(this.config.remoteEndpoint, {
|
|
195
|
+
method: 'POST',
|
|
196
|
+
headers: {
|
|
197
|
+
'Content-Type': 'application/json',
|
|
198
|
+
...this.config.remoteHeaders,
|
|
199
|
+
},
|
|
200
|
+
body: JSON.stringify({ events }),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
// Re-queue on failure
|
|
205
|
+
this.remoteQueue = [...events, ...this.remoteQueue];
|
|
206
|
+
console.warn('[AuditLog] Failed to send events to remote', error);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
isSecurityEvent(type) {
|
|
210
|
+
return type.startsWith('security:') ||
|
|
211
|
+
type === 'tx:blocked' ||
|
|
212
|
+
type === 'rate:limited';
|
|
213
|
+
}
|
|
214
|
+
consoleLogEvent(event) {
|
|
215
|
+
const prefix = this.isSecurityEvent(event.type) ? '🚨' : '📋';
|
|
216
|
+
const level = this.isSecurityEvent(event.type) ? 'warn' : 'info';
|
|
217
|
+
console[level](`${prefix} [Audit] ${event.type}`, {
|
|
218
|
+
walletId: event.walletId,
|
|
219
|
+
accountId: event.accountId,
|
|
220
|
+
risk: event.risk,
|
|
221
|
+
data: event.data,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
queueRemote(event) {
|
|
225
|
+
this.remoteQueue.push(event);
|
|
226
|
+
// Debounce flush
|
|
227
|
+
if (this.flushTimeout) {
|
|
228
|
+
clearTimeout(this.flushTimeout);
|
|
229
|
+
}
|
|
230
|
+
this.flushTimeout = setTimeout(() => {
|
|
231
|
+
this.flushRemote().catch(console.error);
|
|
232
|
+
}, 5000);
|
|
233
|
+
}
|
|
234
|
+
persistEvents() {
|
|
235
|
+
try {
|
|
236
|
+
// Only persist last 100 events
|
|
237
|
+
const toStore = this.events.slice(-100);
|
|
238
|
+
localStorage.setItem('near-connect:audit-log', JSON.stringify(toStore));
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
// Ignore storage errors
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
loadPersistedEvents() {
|
|
245
|
+
try {
|
|
246
|
+
const stored = localStorage.getItem('near-connect:audit-log');
|
|
247
|
+
if (stored) {
|
|
248
|
+
this.events = JSON.parse(stored);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// Ignore parse errors
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
exports.AuditLog = AuditLog;
|
|
257
|
+
/**
|
|
258
|
+
* Create an audit log with default configuration
|
|
259
|
+
*/
|
|
260
|
+
function createAuditLog(config) {
|
|
261
|
+
return new AuditLog({
|
|
262
|
+
enabled: true,
|
|
263
|
+
maxEvents: 1000,
|
|
264
|
+
consoleLog: false, // Set to true for development debugging
|
|
265
|
+
...config,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=audit-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-log.js","sourceRoot":"","sources":["../../src/security/audit-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Security Policy Helper & Security Checklist
|
|
3
|
+
* Hardens browser security against XSS and injection attacks
|
|
4
|
+
*/
|
|
5
|
+
export interface CSPDirectives {
|
|
6
|
+
'default-src'?: string[];
|
|
7
|
+
'script-src'?: string[];
|
|
8
|
+
'style-src'?: string[];
|
|
9
|
+
'connect-src'?: string[];
|
|
10
|
+
'frame-src'?: string[];
|
|
11
|
+
'img-src'?: string[];
|
|
12
|
+
'font-src'?: string[];
|
|
13
|
+
'object-src'?: string[];
|
|
14
|
+
'base-uri'?: string[];
|
|
15
|
+
'form-action'?: string[];
|
|
16
|
+
'frame-ancestors'?: string[];
|
|
17
|
+
'worker-src'?: string[];
|
|
18
|
+
'child-src'?: string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Default CSP directives for apps using NearConnect
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEFAULT_CSP_DIRECTIVES: CSPDirectives;
|
|
24
|
+
/**
|
|
25
|
+
* Generate CSP header string from directives
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateCSP(directives?: CSPDirectives): string;
|
|
28
|
+
/**
|
|
29
|
+
* Get recommended CSP for apps using NearConnect
|
|
30
|
+
*/
|
|
31
|
+
export declare function getRecommendedCSP(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Merge custom CSP directives with defaults
|
|
34
|
+
*/
|
|
35
|
+
export declare function mergeCSP(custom: Partial<CSPDirectives>): CSPDirectives;
|
|
36
|
+
/**
|
|
37
|
+
* Apply CSP via meta tag (for SPAs that can't set headers)
|
|
38
|
+
*/
|
|
39
|
+
export declare function applyCSPMetaTag(directives?: CSPDirectives): void;
|
|
40
|
+
export interface SecurityCheck {
|
|
41
|
+
name: string;
|
|
42
|
+
passed: boolean;
|
|
43
|
+
severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
44
|
+
message: string;
|
|
45
|
+
recommendation?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Run comprehensive security checklist
|
|
49
|
+
*/
|
|
50
|
+
export declare function runSecurityChecklist(): SecurityCheck[];
|
|
51
|
+
/**
|
|
52
|
+
* Get summary of security checklist
|
|
53
|
+
*/
|
|
54
|
+
export declare function getSecuritySummary(checks?: SecurityCheck[]): {
|
|
55
|
+
passed: number;
|
|
56
|
+
failed: number;
|
|
57
|
+
total: number;
|
|
58
|
+
critical: number;
|
|
59
|
+
score: number;
|
|
60
|
+
grade: 'A' | 'B' | 'C' | 'D' | 'F';
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Verify current page has secure context for wallet operations
|
|
64
|
+
*/
|
|
65
|
+
export declare function verifySecureContext(): {
|
|
66
|
+
secure: boolean;
|
|
67
|
+
issues: string[];
|
|
68
|
+
};
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Content Security Policy Helper & Security Checklist
|
|
4
|
+
* Hardens browser security against XSS and injection attacks
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DEFAULT_CSP_DIRECTIVES = void 0;
|
|
8
|
+
exports.generateCSP = generateCSP;
|
|
9
|
+
exports.getRecommendedCSP = getRecommendedCSP;
|
|
10
|
+
exports.mergeCSP = mergeCSP;
|
|
11
|
+
exports.applyCSPMetaTag = applyCSPMetaTag;
|
|
12
|
+
exports.runSecurityChecklist = runSecurityChecklist;
|
|
13
|
+
exports.getSecuritySummary = getSecuritySummary;
|
|
14
|
+
exports.verifySecureContext = verifySecureContext;
|
|
15
|
+
/**
|
|
16
|
+
* Default CSP directives for apps using NearConnect
|
|
17
|
+
*/
|
|
18
|
+
exports.DEFAULT_CSP_DIRECTIVES = {
|
|
19
|
+
// Default fallback
|
|
20
|
+
'default-src': ["'self'"],
|
|
21
|
+
// Scripts - no inline, no eval for security
|
|
22
|
+
'script-src': ["'self'"],
|
|
23
|
+
// Styles - allow inline for wallet UIs (required for dynamic styling)
|
|
24
|
+
'style-src': ["'self'", "'unsafe-inline'"],
|
|
25
|
+
// Connect - RPC endpoints, WalletConnect, verification
|
|
26
|
+
'connect-src': [
|
|
27
|
+
"'self'",
|
|
28
|
+
'https://rpc.mainnet.near.org',
|
|
29
|
+
'https://rpc.testnet.near.org',
|
|
30
|
+
'https://archival-rpc.mainnet.near.org',
|
|
31
|
+
'https://archival-rpc.testnet.near.org',
|
|
32
|
+
'wss://relay.walletconnect.com',
|
|
33
|
+
'https://verify.walletconnect.com',
|
|
34
|
+
'https://explorer-api.mainnet.near.org',
|
|
35
|
+
'https://explorer-api.testnet.near.org',
|
|
36
|
+
],
|
|
37
|
+
// Frames - wallet iframes
|
|
38
|
+
'frame-src': [
|
|
39
|
+
"'self'",
|
|
40
|
+
'https://wallet.nicklatkovich.dev',
|
|
41
|
+
'https://hot-labs.org',
|
|
42
|
+
'https://app.mynearwallet.com',
|
|
43
|
+
'https://wallet.meteorwallet.app',
|
|
44
|
+
'https://my.herewallet.app',
|
|
45
|
+
'https://sender.org',
|
|
46
|
+
'https://wallet.nightly.app',
|
|
47
|
+
'https://wallet.mintbase.xyz',
|
|
48
|
+
],
|
|
49
|
+
// Images
|
|
50
|
+
'img-src': ["'self'", 'data:', 'https:'],
|
|
51
|
+
// Fonts
|
|
52
|
+
'font-src': ["'self'"],
|
|
53
|
+
// No object/embed (Flash, etc.)
|
|
54
|
+
'object-src': ["'none'"],
|
|
55
|
+
// Base URI restriction
|
|
56
|
+
'base-uri': ["'self'"],
|
|
57
|
+
// Form submissions
|
|
58
|
+
'form-action': ["'self'"],
|
|
59
|
+
// Prevent clickjacking
|
|
60
|
+
'frame-ancestors': ["'self'"],
|
|
61
|
+
// Web workers
|
|
62
|
+
'worker-src': ["'self'", 'blob:'],
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Generate CSP header string from directives
|
|
66
|
+
*/
|
|
67
|
+
function generateCSP(directives = exports.DEFAULT_CSP_DIRECTIVES) {
|
|
68
|
+
return Object.entries(directives)
|
|
69
|
+
.map(([key, values]) => `${key} ${values.join(' ')}`)
|
|
70
|
+
.join('; ');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get recommended CSP for apps using NearConnect
|
|
74
|
+
*/
|
|
75
|
+
function getRecommendedCSP() {
|
|
76
|
+
return generateCSP(exports.DEFAULT_CSP_DIRECTIVES);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Merge custom CSP directives with defaults
|
|
80
|
+
*/
|
|
81
|
+
function mergeCSP(custom) {
|
|
82
|
+
const merged = { ...exports.DEFAULT_CSP_DIRECTIVES };
|
|
83
|
+
for (const [key, values] of Object.entries(custom)) {
|
|
84
|
+
const directive = key;
|
|
85
|
+
merged[directive] = [
|
|
86
|
+
...(merged[directive] || []),
|
|
87
|
+
...values,
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
return merged;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Apply CSP via meta tag (for SPAs that can't set headers)
|
|
94
|
+
*/
|
|
95
|
+
function applyCSPMetaTag(directives) {
|
|
96
|
+
if (typeof document === 'undefined')
|
|
97
|
+
return;
|
|
98
|
+
const csp = generateCSP(directives);
|
|
99
|
+
// Remove existing CSP meta tag
|
|
100
|
+
const existing = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
|
|
101
|
+
if (existing) {
|
|
102
|
+
existing.remove();
|
|
103
|
+
}
|
|
104
|
+
// Add new CSP meta tag
|
|
105
|
+
const meta = document.createElement('meta');
|
|
106
|
+
meta.httpEquiv = 'Content-Security-Policy';
|
|
107
|
+
meta.content = csp;
|
|
108
|
+
document.head.appendChild(meta);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Run comprehensive security checklist
|
|
112
|
+
*/
|
|
113
|
+
function runSecurityChecklist() {
|
|
114
|
+
const checks = [];
|
|
115
|
+
// Browser environment check
|
|
116
|
+
if (typeof window === 'undefined') {
|
|
117
|
+
return [{
|
|
118
|
+
name: 'Environment',
|
|
119
|
+
passed: true,
|
|
120
|
+
severity: 'info',
|
|
121
|
+
message: 'Running in non-browser environment',
|
|
122
|
+
}];
|
|
123
|
+
}
|
|
124
|
+
// 1. Secure context (HTTPS)
|
|
125
|
+
checks.push({
|
|
126
|
+
name: 'Secure Context',
|
|
127
|
+
passed: window.isSecureContext,
|
|
128
|
+
severity: 'critical',
|
|
129
|
+
message: window.isSecureContext
|
|
130
|
+
? 'Running in secure context (HTTPS)'
|
|
131
|
+
: 'Not running in secure context',
|
|
132
|
+
recommendation: window.isSecureContext
|
|
133
|
+
? undefined
|
|
134
|
+
: 'Deploy application over HTTPS for production use',
|
|
135
|
+
});
|
|
136
|
+
// 2. Frame protection (clickjacking)
|
|
137
|
+
const isFramed = window.self !== window.top;
|
|
138
|
+
checks.push({
|
|
139
|
+
name: 'Frame Protection',
|
|
140
|
+
passed: !isFramed,
|
|
141
|
+
severity: 'high',
|
|
142
|
+
message: isFramed
|
|
143
|
+
? 'Page is embedded in an iframe - potential clickjacking risk'
|
|
144
|
+
: 'Page is not embedded in iframe',
|
|
145
|
+
recommendation: isFramed
|
|
146
|
+
? 'Ensure the parent frame is trusted or add frame-ancestors CSP directive'
|
|
147
|
+
: undefined,
|
|
148
|
+
});
|
|
149
|
+
// 3. Web Crypto API
|
|
150
|
+
const hasCrypto = !!(crypto?.subtle);
|
|
151
|
+
checks.push({
|
|
152
|
+
name: 'Web Crypto API',
|
|
153
|
+
passed: hasCrypto,
|
|
154
|
+
severity: 'critical',
|
|
155
|
+
message: hasCrypto
|
|
156
|
+
? 'Web Crypto API available for secure operations'
|
|
157
|
+
: 'Web Crypto API not available',
|
|
158
|
+
recommendation: hasCrypto
|
|
159
|
+
? undefined
|
|
160
|
+
: 'Ensure browser supports Web Crypto API (requires HTTPS)',
|
|
161
|
+
});
|
|
162
|
+
// 4. Storage availability
|
|
163
|
+
const hasStorage = !!localStorage && !!sessionStorage;
|
|
164
|
+
checks.push({
|
|
165
|
+
name: 'Storage',
|
|
166
|
+
passed: hasStorage,
|
|
167
|
+
severity: 'medium',
|
|
168
|
+
message: hasStorage
|
|
169
|
+
? 'Local and session storage available'
|
|
170
|
+
: 'Storage APIs not available',
|
|
171
|
+
recommendation: hasStorage
|
|
172
|
+
? undefined
|
|
173
|
+
: 'Enable storage in browser settings for session persistence',
|
|
174
|
+
});
|
|
175
|
+
// 5. WebHID for hardware wallets
|
|
176
|
+
const hasWebHID = 'hid' in navigator;
|
|
177
|
+
checks.push({
|
|
178
|
+
name: 'WebHID Support',
|
|
179
|
+
passed: hasWebHID,
|
|
180
|
+
severity: 'low',
|
|
181
|
+
message: hasWebHID
|
|
182
|
+
? 'Hardware wallet support available (WebHID)'
|
|
183
|
+
: 'Hardware wallet support not available',
|
|
184
|
+
recommendation: hasWebHID
|
|
185
|
+
? undefined
|
|
186
|
+
: 'Use Chrome/Edge for hardware wallet (Ledger) support',
|
|
187
|
+
});
|
|
188
|
+
// 6. Cross-origin isolation
|
|
189
|
+
checks.push({
|
|
190
|
+
name: 'Cross-Origin Isolation',
|
|
191
|
+
passed: crossOriginIsolated,
|
|
192
|
+
severity: 'low',
|
|
193
|
+
message: crossOriginIsolated
|
|
194
|
+
? 'Cross-origin isolated for enhanced security'
|
|
195
|
+
: 'Not cross-origin isolated',
|
|
196
|
+
recommendation: crossOriginIsolated
|
|
197
|
+
? undefined
|
|
198
|
+
: 'Add COOP/COEP headers for enhanced isolation (optional)',
|
|
199
|
+
});
|
|
200
|
+
// 7. Check for common vulnerabilities
|
|
201
|
+
const hasEval = testEvalAvailable();
|
|
202
|
+
checks.push({
|
|
203
|
+
name: 'Eval Disabled',
|
|
204
|
+
passed: !hasEval,
|
|
205
|
+
severity: 'medium',
|
|
206
|
+
message: hasEval
|
|
207
|
+
? 'eval() is available - potential code injection risk'
|
|
208
|
+
: 'eval() is properly restricted',
|
|
209
|
+
recommendation: hasEval
|
|
210
|
+
? 'Add script-src CSP without unsafe-eval'
|
|
211
|
+
: undefined,
|
|
212
|
+
});
|
|
213
|
+
// 8. Service Worker scope
|
|
214
|
+
const hasSW = 'serviceWorker' in navigator;
|
|
215
|
+
checks.push({
|
|
216
|
+
name: 'Service Worker',
|
|
217
|
+
passed: true,
|
|
218
|
+
severity: 'info',
|
|
219
|
+
message: hasSW
|
|
220
|
+
? 'Service Worker API available'
|
|
221
|
+
: 'Service Worker not available',
|
|
222
|
+
});
|
|
223
|
+
// 9. Permissions API
|
|
224
|
+
const hasPermissions = 'permissions' in navigator;
|
|
225
|
+
checks.push({
|
|
226
|
+
name: 'Permissions API',
|
|
227
|
+
passed: hasPermissions,
|
|
228
|
+
severity: 'info',
|
|
229
|
+
message: hasPermissions
|
|
230
|
+
? 'Permissions API available for feature detection'
|
|
231
|
+
: 'Permissions API not available',
|
|
232
|
+
});
|
|
233
|
+
// 10. Referrer policy
|
|
234
|
+
const referrerMeta = document.querySelector('meta[name="referrer"]');
|
|
235
|
+
const hasStrictReferrer = referrerMeta?.getAttribute('content')?.includes('strict') ||
|
|
236
|
+
referrerMeta?.getAttribute('content') === 'no-referrer';
|
|
237
|
+
checks.push({
|
|
238
|
+
name: 'Referrer Policy',
|
|
239
|
+
passed: hasStrictReferrer,
|
|
240
|
+
severity: 'low',
|
|
241
|
+
message: hasStrictReferrer
|
|
242
|
+
? 'Strict referrer policy configured'
|
|
243
|
+
: 'Consider adding strict referrer policy',
|
|
244
|
+
recommendation: hasStrictReferrer
|
|
245
|
+
? undefined
|
|
246
|
+
: 'Add <meta name="referrer" content="strict-origin-when-cross-origin">',
|
|
247
|
+
});
|
|
248
|
+
return checks;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get summary of security checklist
|
|
252
|
+
*/
|
|
253
|
+
function getSecuritySummary(checks) {
|
|
254
|
+
const results = checks || runSecurityChecklist();
|
|
255
|
+
const passed = results.filter(c => c.passed).length;
|
|
256
|
+
const failed = results.filter(c => !c.passed).length;
|
|
257
|
+
const critical = results.filter(c => !c.passed && c.severity === 'critical').length;
|
|
258
|
+
const total = results.length;
|
|
259
|
+
// Calculate weighted score
|
|
260
|
+
const weights = { critical: 30, high: 20, medium: 10, low: 5, info: 0 };
|
|
261
|
+
let maxScore = 0;
|
|
262
|
+
let actualScore = 0;
|
|
263
|
+
for (const check of results) {
|
|
264
|
+
const weight = weights[check.severity];
|
|
265
|
+
maxScore += weight;
|
|
266
|
+
if (check.passed) {
|
|
267
|
+
actualScore += weight;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const score = maxScore > 0 ? Math.round((actualScore / maxScore) * 100) : 100;
|
|
271
|
+
// Grade based on score and critical failures
|
|
272
|
+
let grade;
|
|
273
|
+
if (critical > 0) {
|
|
274
|
+
grade = 'F';
|
|
275
|
+
}
|
|
276
|
+
else if (score >= 90) {
|
|
277
|
+
grade = 'A';
|
|
278
|
+
}
|
|
279
|
+
else if (score >= 80) {
|
|
280
|
+
grade = 'B';
|
|
281
|
+
}
|
|
282
|
+
else if (score >= 70) {
|
|
283
|
+
grade = 'C';
|
|
284
|
+
}
|
|
285
|
+
else if (score >= 60) {
|
|
286
|
+
grade = 'D';
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
grade = 'F';
|
|
290
|
+
}
|
|
291
|
+
return { passed, failed, total, critical, score, grade };
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Test if eval is available (should be blocked by CSP)
|
|
295
|
+
*/
|
|
296
|
+
function testEvalAvailable() {
|
|
297
|
+
try {
|
|
298
|
+
// eslint-disable-next-line no-eval
|
|
299
|
+
eval('1');
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Verify current page has secure context for wallet operations
|
|
308
|
+
*/
|
|
309
|
+
function verifySecureContext() {
|
|
310
|
+
const issues = [];
|
|
311
|
+
if (typeof window === 'undefined') {
|
|
312
|
+
return { secure: true, issues: [] };
|
|
313
|
+
}
|
|
314
|
+
if (!window.isSecureContext) {
|
|
315
|
+
issues.push('Page is not in a secure context (HTTPS required)');
|
|
316
|
+
}
|
|
317
|
+
if (window.self !== window.top) {
|
|
318
|
+
issues.push('Page is embedded in an iframe');
|
|
319
|
+
}
|
|
320
|
+
if (!crypto?.subtle) {
|
|
321
|
+
issues.push('Web Crypto API not available');
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
secure: issues.length === 0,
|
|
325
|
+
issues,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=csp.js.map
|