@spektre/veil 0.1.0 → 0.1.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/dist/hooks/index.d.ts +0 -3
- package/dist/index.d.ts +5 -6
- package/dist/index.esm.js +237 -96
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +235 -96
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +21 -24
- package/package.json +2 -1
- package/dist/components/VeilProvider.d.ts +0 -9
- package/dist/hooks/useVeil.d.ts +0 -2
package/dist/hooks/index.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { default as VeilProvider } from './components/VeilProvider';
|
|
2
|
-
export { useVeil, useSpektre, useProtectedFetch } from './hooks';
|
|
3
|
-
export { SpektreContext } from './SpektreContext';
|
|
4
|
-
export { SpektreProvider } from './SpektreProvider';
|
|
5
1
|
export { SecurityGate } from './SecurityGate';
|
|
6
|
-
export
|
|
7
|
-
export
|
|
2
|
+
export { SpektreProvider } from './SpektreProvider';
|
|
3
|
+
export { SpektreContext } from './SpektreContext';
|
|
4
|
+
export { useSpektre } from './hooks/useSpektre';
|
|
5
|
+
export { useProtectedFetch } from './hooks/useProtectedFetch';
|
|
6
|
+
export type { SecurityGateProps, SpektreConfig, SpektreState, ProtectionState, MonitoringState, BlockedRequest, BlockedAttack, TamperingDetails, VeilConfig, VeilState, VeilProps, VeilContextType, } from './types';
|
package/dist/index.esm.js
CHANGED
|
@@ -1,81 +1,8 @@
|
|
|
1
|
-
import React, { createContext,
|
|
2
|
-
|
|
3
|
-
const VeilContext = createContext(undefined);
|
|
4
|
-
const VeilProvider = ({ config, children }) => {
|
|
5
|
-
const isMonitoring = useMemo(() => config.enableMonitoring ?? false, [config.enableMonitoring]);
|
|
6
|
-
const logEvent = useCallback((event, data) => {
|
|
7
|
-
if (isMonitoring) {
|
|
8
|
-
console.log('[Veil]', event, data);
|
|
9
|
-
}
|
|
10
|
-
}, [isMonitoring]);
|
|
11
|
-
const value = useMemo(() => ({
|
|
12
|
-
config,
|
|
13
|
-
isMonitoring,
|
|
14
|
-
logEvent,
|
|
15
|
-
}), [config, isMonitoring, logEvent]);
|
|
16
|
-
return React.createElement(VeilContext.Provider, { value: value }, children);
|
|
17
|
-
};
|
|
1
|
+
import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
18
2
|
|
|
19
3
|
const SpektreContext = createContext(null);
|
|
20
4
|
SpektreContext.displayName = 'SpektreContext';
|
|
21
5
|
|
|
22
|
-
const useSpektre = () => {
|
|
23
|
-
const context = useContext(SpektreContext);
|
|
24
|
-
if (!context) {
|
|
25
|
-
throw new Error('useSpektre must be used within a SecurityGate component');
|
|
26
|
-
}
|
|
27
|
-
const runScan = async () => {
|
|
28
|
-
if (typeof window.securityScan === 'function') {
|
|
29
|
-
await window.securityScan();
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const getTelemetry = () => {
|
|
33
|
-
if (typeof window.getSecurityTelemetry === 'function') {
|
|
34
|
-
return window.getSecurityTelemetry();
|
|
35
|
-
}
|
|
36
|
-
return context.monitoring;
|
|
37
|
-
};
|
|
38
|
-
const getProtectionStats = () => {
|
|
39
|
-
if (typeof window.getProtectionStats === 'function') {
|
|
40
|
-
return window.getProtectionStats();
|
|
41
|
-
}
|
|
42
|
-
return context.protection;
|
|
43
|
-
};
|
|
44
|
-
return {
|
|
45
|
-
isVerified: context.isVerified,
|
|
46
|
-
sessionId: context.sessionId,
|
|
47
|
-
protectionEnabled: context.protection?.enabled || false,
|
|
48
|
-
blockedRequests: context.protection?.blockedRequests || [],
|
|
49
|
-
totalBlocked: context.protection?.totalBlocked || 0,
|
|
50
|
-
secretExposures: context.monitoring?.secretExposures || 0,
|
|
51
|
-
scriptProfiles: context.monitoring?.scriptProfiles || 0,
|
|
52
|
-
supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
|
|
53
|
-
sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
|
|
54
|
-
runScan,
|
|
55
|
-
getTelemetry,
|
|
56
|
-
getProtectionStats,
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const useProtectedFetch = () => {
|
|
61
|
-
const { isVerified } = useSpektre();
|
|
62
|
-
const protectedFetch = async (url, options) => {
|
|
63
|
-
if (!isVerified) {
|
|
64
|
-
throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
|
|
65
|
-
}
|
|
66
|
-
return fetch(url, options);
|
|
67
|
-
};
|
|
68
|
-
return protectedFetch;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const useVeil = () => {
|
|
72
|
-
const context = useContext(VeilContext);
|
|
73
|
-
if (context === undefined) {
|
|
74
|
-
throw new Error('useVeil must be used within a VeilProvider');
|
|
75
|
-
}
|
|
76
|
-
return context;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
6
|
const SpektreProvider = ({ value, children }) => {
|
|
80
7
|
return React.createElement(SpektreContext.Provider, { value: value }, children);
|
|
81
8
|
};
|
|
@@ -89,6 +16,9 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
89
16
|
sessionId: null,
|
|
90
17
|
});
|
|
91
18
|
useEffect(() => {
|
|
19
|
+
// Set tampering detection marker
|
|
20
|
+
sessionStorage.setItem('spektre_js_enabled', 'true');
|
|
21
|
+
sessionStorage.setItem('spektre_init_time', Date.now().toString());
|
|
92
22
|
const scriptUrl = `${SUPABASE_BASE_URL}/functions/v1/scanner_client`;
|
|
93
23
|
const script = document.createElement('script');
|
|
94
24
|
script.src = `${scriptUrl}?apiKey=${encodeURIComponent(apiKey)}`;
|
|
@@ -118,7 +48,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
118
48
|
script.setAttribute('data-session', String(config.modules.sessionProtection));
|
|
119
49
|
}
|
|
120
50
|
if (config.modules.activeProtection !== undefined) {
|
|
121
|
-
script.setAttribute('data-
|
|
51
|
+
script.setAttribute('data-protection', String(config.modules.activeProtection));
|
|
122
52
|
}
|
|
123
53
|
}
|
|
124
54
|
script.onload = () => {
|
|
@@ -141,6 +71,8 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
141
71
|
protection,
|
|
142
72
|
monitoring,
|
|
143
73
|
});
|
|
74
|
+
// Start tampering detection after successful load
|
|
75
|
+
startTamperingDetection(config);
|
|
144
76
|
}
|
|
145
77
|
catch (err) {
|
|
146
78
|
setState({
|
|
@@ -169,6 +101,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
169
101
|
if (script.parentNode) {
|
|
170
102
|
script.parentNode.removeChild(script);
|
|
171
103
|
}
|
|
104
|
+
stopTamperingDetection();
|
|
172
105
|
};
|
|
173
106
|
}, [apiKey, config]);
|
|
174
107
|
const handleRetry = () => {
|
|
@@ -197,70 +130,229 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
197
130
|
if (fallback) {
|
|
198
131
|
return React.createElement(React.Fragment, null, fallback);
|
|
199
132
|
}
|
|
200
|
-
return (React.createElement("div", { style: styles.
|
|
133
|
+
return (React.createElement("div", { style: styles.errorContainer },
|
|
201
134
|
React.createElement("div", { style: styles.content },
|
|
202
135
|
React.createElement("div", { style: { ...styles.icon, color: '#ef4444' } },
|
|
203
136
|
React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
204
137
|
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
205
138
|
React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
206
139
|
React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" }))),
|
|
207
|
-
React.createElement("h2", { style: styles.
|
|
208
|
-
React.createElement("p", { style: styles.
|
|
209
|
-
React.createElement("
|
|
140
|
+
React.createElement("h2", { style: styles.errorTitle }, "Security Protection Required"),
|
|
141
|
+
React.createElement("p", { style: styles.errorMessage }, "This application requires Spektre security protection to run safely."),
|
|
142
|
+
React.createElement("p", { style: styles.errorDetails }, state.error || 'Unable to verify application security'),
|
|
143
|
+
React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry Loading"))));
|
|
210
144
|
}
|
|
211
145
|
return React.createElement(SpektreProvider, { value: state }, children);
|
|
212
146
|
};
|
|
147
|
+
// Tampering detection
|
|
148
|
+
let tamperingInterval = null;
|
|
149
|
+
let fetchIntegrityHash = null;
|
|
150
|
+
function startTamperingDetection(config) {
|
|
151
|
+
// Calculate integrity hash of fetch function
|
|
152
|
+
if (typeof window.fetch === 'function') {
|
|
153
|
+
fetchIntegrityHash = hashCode(window.fetch.toString());
|
|
154
|
+
}
|
|
155
|
+
tamperingInterval = window.setInterval(() => {
|
|
156
|
+
// Check 1: Verify JavaScript marker is still present
|
|
157
|
+
const jsEnabled = sessionStorage.getItem('spektre_js_enabled');
|
|
158
|
+
if (!jsEnabled) {
|
|
159
|
+
handleTampering('JavaScript marker removed', config);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Check 2: Verify Spektre script is still in DOM
|
|
163
|
+
const scriptExists = document.querySelector('script[src*="scanner_client"]');
|
|
164
|
+
if (!scriptExists) {
|
|
165
|
+
handleTampering('Security script removed from page', config);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Check 3: Verify fetch function hasn't been tampered with
|
|
169
|
+
if (typeof window.fetch === 'function') {
|
|
170
|
+
const currentHash = hashCode(window.fetch.toString());
|
|
171
|
+
if (fetchIntegrityHash && currentHash !== fetchIntegrityHash) {
|
|
172
|
+
// Fetch function was modified
|
|
173
|
+
const fetchCode = window.fetch.toString();
|
|
174
|
+
// Check if it still has Spektre protection
|
|
175
|
+
if (!fetchCode.includes('Spektre') && !fetchCode.includes('PROTECTION')) {
|
|
176
|
+
handleTampering('Security protection has been disabled', config);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
handleTampering('Fetch function removed', config);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Check 4: Verify protection stats function exists
|
|
186
|
+
if (typeof window.getProtectionStats !== 'function') {
|
|
187
|
+
handleTampering('Security monitoring disabled', config);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}, 2000); // Check every 2 seconds
|
|
191
|
+
}
|
|
192
|
+
function stopTamperingDetection() {
|
|
193
|
+
if (tamperingInterval) {
|
|
194
|
+
clearInterval(tamperingInterval);
|
|
195
|
+
tamperingInterval = null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function handleTampering(reason, config) {
|
|
199
|
+
console.error('[Spektre SecurityGate] TAMPERING DETECTED:', reason);
|
|
200
|
+
// Stop checking to prevent infinite loops
|
|
201
|
+
stopTamperingDetection();
|
|
202
|
+
// Call callback if provided
|
|
203
|
+
if (config?.onTamperingDetected) {
|
|
204
|
+
config.onTamperingDetected(reason);
|
|
205
|
+
}
|
|
206
|
+
// Lock down the application
|
|
207
|
+
const root = document.getElementById('root');
|
|
208
|
+
if (root) {
|
|
209
|
+
root.innerHTML = '';
|
|
210
|
+
}
|
|
211
|
+
document.body.innerHTML = `
|
|
212
|
+
<div style="
|
|
213
|
+
position: fixed;
|
|
214
|
+
top: 0;
|
|
215
|
+
left: 0;
|
|
216
|
+
width: 100%;
|
|
217
|
+
height: 100%;
|
|
218
|
+
background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
|
|
219
|
+
color: white;
|
|
220
|
+
display: flex;
|
|
221
|
+
align-items: center;
|
|
222
|
+
justify-content: center;
|
|
223
|
+
flex-direction: column;
|
|
224
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
225
|
+
z-index: 999999;
|
|
226
|
+
">
|
|
227
|
+
<div style="max-width: 500px; text-align: center; padding: 40px;">
|
|
228
|
+
<div style="font-size: 72px; margin-bottom: 24px;">⛔</div>
|
|
229
|
+
<h1 style="font-size: 28px; font-weight: 600; margin-bottom: 16px;">
|
|
230
|
+
Security Violation Detected
|
|
231
|
+
</h1>
|
|
232
|
+
<p style="font-size: 16px; line-height: 1.6; opacity: 0.9; margin-bottom: 24px;">
|
|
233
|
+
This application has been locked due to security tampering.
|
|
234
|
+
</p>
|
|
235
|
+
<div style="
|
|
236
|
+
background: rgba(255, 255, 255, 0.1);
|
|
237
|
+
border-radius: 8px;
|
|
238
|
+
padding: 16px;
|
|
239
|
+
margin-bottom: 24px;
|
|
240
|
+
font-size: 14px;
|
|
241
|
+
font-family: monospace;
|
|
242
|
+
">
|
|
243
|
+
${reason}
|
|
244
|
+
</div>
|
|
245
|
+
<button onclick="location.reload()" style="
|
|
246
|
+
padding: 12px 32px;
|
|
247
|
+
font-size: 16px;
|
|
248
|
+
font-weight: 500;
|
|
249
|
+
background: white;
|
|
250
|
+
color: #dc2626;
|
|
251
|
+
border: none;
|
|
252
|
+
border-radius: 8px;
|
|
253
|
+
cursor: pointer;
|
|
254
|
+
transition: transform 0.2s;
|
|
255
|
+
" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
|
|
256
|
+
Reload Application
|
|
257
|
+
</button>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
`;
|
|
261
|
+
}
|
|
262
|
+
// Simple hash function for integrity checking
|
|
263
|
+
function hashCode(str) {
|
|
264
|
+
let hash = 0;
|
|
265
|
+
for (let i = 0; i < str.length; i++) {
|
|
266
|
+
const char = str.charCodeAt(i);
|
|
267
|
+
hash = ((hash << 5) - hash) + char;
|
|
268
|
+
hash = hash & hash;
|
|
269
|
+
}
|
|
270
|
+
return hash.toString(36);
|
|
271
|
+
}
|
|
213
272
|
const styles = {
|
|
214
273
|
container: {
|
|
215
274
|
display: 'flex',
|
|
216
275
|
alignItems: 'center',
|
|
217
276
|
justifyContent: 'center',
|
|
218
277
|
minHeight: '100vh',
|
|
219
|
-
|
|
278
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
279
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
280
|
+
},
|
|
281
|
+
errorContainer: {
|
|
282
|
+
display: 'flex',
|
|
283
|
+
alignItems: 'center',
|
|
284
|
+
justifyContent: 'center',
|
|
285
|
+
minHeight: '100vh',
|
|
286
|
+
background: 'linear-gradient(135deg, #1f2937 0%, #111827 100%)',
|
|
220
287
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
221
288
|
},
|
|
222
289
|
content: {
|
|
223
290
|
textAlign: 'center',
|
|
224
291
|
padding: '2rem',
|
|
225
|
-
maxWidth: '
|
|
292
|
+
maxWidth: '500px',
|
|
293
|
+
background: 'rgba(255, 255, 255, 0.95)',
|
|
294
|
+
borderRadius: '16px',
|
|
295
|
+
boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)',
|
|
226
296
|
},
|
|
227
297
|
icon: {
|
|
228
|
-
color: '#
|
|
229
|
-
marginBottom: '
|
|
298
|
+
color: '#667eea',
|
|
299
|
+
marginBottom: '1.5rem',
|
|
230
300
|
display: 'flex',
|
|
231
301
|
justifyContent: 'center',
|
|
232
302
|
},
|
|
233
303
|
title: {
|
|
234
|
-
fontSize: '1.
|
|
304
|
+
fontSize: '1.75rem',
|
|
235
305
|
fontWeight: '600',
|
|
236
306
|
color: '#111827',
|
|
237
|
-
marginBottom: '0.
|
|
307
|
+
marginBottom: '0.75rem',
|
|
238
308
|
},
|
|
239
309
|
message: {
|
|
240
310
|
fontSize: '1rem',
|
|
241
311
|
color: '#6b7280',
|
|
242
312
|
marginBottom: '1.5rem',
|
|
243
|
-
lineHeight: '1.
|
|
313
|
+
lineHeight: '1.6',
|
|
314
|
+
},
|
|
315
|
+
errorTitle: {
|
|
316
|
+
fontSize: '1.75rem',
|
|
317
|
+
fontWeight: '600',
|
|
318
|
+
color: '#111827',
|
|
319
|
+
marginBottom: '0.75rem',
|
|
320
|
+
},
|
|
321
|
+
errorMessage: {
|
|
322
|
+
fontSize: '1rem',
|
|
323
|
+
color: '#6b7280',
|
|
324
|
+
marginBottom: '1rem',
|
|
325
|
+
lineHeight: '1.6',
|
|
326
|
+
},
|
|
327
|
+
errorDetails: {
|
|
328
|
+
fontSize: '0.875rem',
|
|
329
|
+
color: '#ef4444',
|
|
330
|
+
marginBottom: '1.5rem',
|
|
331
|
+
padding: '0.75rem',
|
|
332
|
+
background: '#fef2f2',
|
|
333
|
+
borderRadius: '8px',
|
|
334
|
+
fontFamily: 'monospace',
|
|
244
335
|
},
|
|
245
336
|
spinner: {
|
|
246
|
-
width: '
|
|
247
|
-
height: '
|
|
248
|
-
border: '
|
|
249
|
-
borderTopColor: '#
|
|
337
|
+
width: '40px',
|
|
338
|
+
height: '40px',
|
|
339
|
+
border: '4px solid rgba(255, 255, 255, 0.3)',
|
|
340
|
+
borderTopColor: '#667eea',
|
|
250
341
|
borderRadius: '50%',
|
|
251
342
|
margin: '0 auto',
|
|
252
343
|
animation: 'spin 1s linear infinite',
|
|
253
344
|
},
|
|
254
345
|
button: {
|
|
255
|
-
backgroundColor: '#
|
|
346
|
+
backgroundColor: '#667eea',
|
|
256
347
|
color: 'white',
|
|
257
348
|
border: 'none',
|
|
258
|
-
borderRadius: '
|
|
259
|
-
padding: '0.
|
|
349
|
+
borderRadius: '8px',
|
|
350
|
+
padding: '0.875rem 2rem',
|
|
260
351
|
fontSize: '1rem',
|
|
261
|
-
fontWeight: '
|
|
352
|
+
fontWeight: '600',
|
|
262
353
|
cursor: 'pointer',
|
|
263
|
-
transition: '
|
|
354
|
+
transition: 'all 0.2s',
|
|
355
|
+
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)',
|
|
264
356
|
},
|
|
265
357
|
};
|
|
266
358
|
const styleSheet = document.createElement('style');
|
|
@@ -273,5 +365,54 @@ styleSheet.textContent = `
|
|
|
273
365
|
`;
|
|
274
366
|
document.head.appendChild(styleSheet);
|
|
275
367
|
|
|
276
|
-
|
|
368
|
+
const useSpektre = () => {
|
|
369
|
+
const context = useContext(SpektreContext);
|
|
370
|
+
if (!context) {
|
|
371
|
+
throw new Error('useSpektre must be used within a SecurityGate component');
|
|
372
|
+
}
|
|
373
|
+
const runScan = async () => {
|
|
374
|
+
if (typeof window.securityScan === 'function') {
|
|
375
|
+
await window.securityScan();
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
const getTelemetry = () => {
|
|
379
|
+
if (typeof window.getSecurityTelemetry === 'function') {
|
|
380
|
+
return window.getSecurityTelemetry();
|
|
381
|
+
}
|
|
382
|
+
return context.monitoring;
|
|
383
|
+
};
|
|
384
|
+
const getProtectionStats = () => {
|
|
385
|
+
if (typeof window.getProtectionStats === 'function') {
|
|
386
|
+
return window.getProtectionStats();
|
|
387
|
+
}
|
|
388
|
+
return context.protection;
|
|
389
|
+
};
|
|
390
|
+
return {
|
|
391
|
+
isVerified: context.isVerified,
|
|
392
|
+
sessionId: context.sessionId,
|
|
393
|
+
protectionEnabled: context.protection?.enabled || false,
|
|
394
|
+
blockedRequests: context.protection?.blockedRequests || [],
|
|
395
|
+
totalBlocked: context.protection?.totalBlocked || 0,
|
|
396
|
+
secretExposures: context.monitoring?.secretExposures || 0,
|
|
397
|
+
scriptProfiles: context.monitoring?.scriptProfiles || 0,
|
|
398
|
+
supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
|
|
399
|
+
sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
|
|
400
|
+
runScan,
|
|
401
|
+
getTelemetry,
|
|
402
|
+
getProtectionStats,
|
|
403
|
+
};
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
const useProtectedFetch = () => {
|
|
407
|
+
const { isVerified } = useSpektre();
|
|
408
|
+
const protectedFetch = async (url, options) => {
|
|
409
|
+
if (!isVerified) {
|
|
410
|
+
throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
|
|
411
|
+
}
|
|
412
|
+
return fetch(url, options);
|
|
413
|
+
};
|
|
414
|
+
return protectedFetch;
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
export { SecurityGate, SpektreContext, SpektreProvider, useProtectedFetch, useSpektre };
|
|
277
418
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -2,82 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
|
|
5
|
-
const VeilContext = React.createContext(undefined);
|
|
6
|
-
const VeilProvider = ({ config, children }) => {
|
|
7
|
-
const isMonitoring = React.useMemo(() => config.enableMonitoring ?? false, [config.enableMonitoring]);
|
|
8
|
-
const logEvent = React.useCallback((event, data) => {
|
|
9
|
-
if (isMonitoring) {
|
|
10
|
-
console.log('[Veil]', event, data);
|
|
11
|
-
}
|
|
12
|
-
}, [isMonitoring]);
|
|
13
|
-
const value = React.useMemo(() => ({
|
|
14
|
-
config,
|
|
15
|
-
isMonitoring,
|
|
16
|
-
logEvent,
|
|
17
|
-
}), [config, isMonitoring, logEvent]);
|
|
18
|
-
return React.createElement(VeilContext.Provider, { value: value }, children);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
5
|
const SpektreContext = React.createContext(null);
|
|
22
6
|
SpektreContext.displayName = 'SpektreContext';
|
|
23
7
|
|
|
24
|
-
const useSpektre = () => {
|
|
25
|
-
const context = React.useContext(SpektreContext);
|
|
26
|
-
if (!context) {
|
|
27
|
-
throw new Error('useSpektre must be used within a SecurityGate component');
|
|
28
|
-
}
|
|
29
|
-
const runScan = async () => {
|
|
30
|
-
if (typeof window.securityScan === 'function') {
|
|
31
|
-
await window.securityScan();
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
const getTelemetry = () => {
|
|
35
|
-
if (typeof window.getSecurityTelemetry === 'function') {
|
|
36
|
-
return window.getSecurityTelemetry();
|
|
37
|
-
}
|
|
38
|
-
return context.monitoring;
|
|
39
|
-
};
|
|
40
|
-
const getProtectionStats = () => {
|
|
41
|
-
if (typeof window.getProtectionStats === 'function') {
|
|
42
|
-
return window.getProtectionStats();
|
|
43
|
-
}
|
|
44
|
-
return context.protection;
|
|
45
|
-
};
|
|
46
|
-
return {
|
|
47
|
-
isVerified: context.isVerified,
|
|
48
|
-
sessionId: context.sessionId,
|
|
49
|
-
protectionEnabled: context.protection?.enabled || false,
|
|
50
|
-
blockedRequests: context.protection?.blockedRequests || [],
|
|
51
|
-
totalBlocked: context.protection?.totalBlocked || 0,
|
|
52
|
-
secretExposures: context.monitoring?.secretExposures || 0,
|
|
53
|
-
scriptProfiles: context.monitoring?.scriptProfiles || 0,
|
|
54
|
-
supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
|
|
55
|
-
sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
|
|
56
|
-
runScan,
|
|
57
|
-
getTelemetry,
|
|
58
|
-
getProtectionStats,
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const useProtectedFetch = () => {
|
|
63
|
-
const { isVerified } = useSpektre();
|
|
64
|
-
const protectedFetch = async (url, options) => {
|
|
65
|
-
if (!isVerified) {
|
|
66
|
-
throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
|
|
67
|
-
}
|
|
68
|
-
return fetch(url, options);
|
|
69
|
-
};
|
|
70
|
-
return protectedFetch;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const useVeil = () => {
|
|
74
|
-
const context = React.useContext(VeilContext);
|
|
75
|
-
if (context === undefined) {
|
|
76
|
-
throw new Error('useVeil must be used within a VeilProvider');
|
|
77
|
-
}
|
|
78
|
-
return context;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
8
|
const SpektreProvider = ({ value, children }) => {
|
|
82
9
|
return React.createElement(SpektreContext.Provider, { value: value }, children);
|
|
83
10
|
};
|
|
@@ -91,6 +18,9 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
91
18
|
sessionId: null,
|
|
92
19
|
});
|
|
93
20
|
React.useEffect(() => {
|
|
21
|
+
// Set tampering detection marker
|
|
22
|
+
sessionStorage.setItem('spektre_js_enabled', 'true');
|
|
23
|
+
sessionStorage.setItem('spektre_init_time', Date.now().toString());
|
|
94
24
|
const scriptUrl = `${SUPABASE_BASE_URL}/functions/v1/scanner_client`;
|
|
95
25
|
const script = document.createElement('script');
|
|
96
26
|
script.src = `${scriptUrl}?apiKey=${encodeURIComponent(apiKey)}`;
|
|
@@ -120,7 +50,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
120
50
|
script.setAttribute('data-session', String(config.modules.sessionProtection));
|
|
121
51
|
}
|
|
122
52
|
if (config.modules.activeProtection !== undefined) {
|
|
123
|
-
script.setAttribute('data-
|
|
53
|
+
script.setAttribute('data-protection', String(config.modules.activeProtection));
|
|
124
54
|
}
|
|
125
55
|
}
|
|
126
56
|
script.onload = () => {
|
|
@@ -143,6 +73,8 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
143
73
|
protection,
|
|
144
74
|
monitoring,
|
|
145
75
|
});
|
|
76
|
+
// Start tampering detection after successful load
|
|
77
|
+
startTamperingDetection(config);
|
|
146
78
|
}
|
|
147
79
|
catch (err) {
|
|
148
80
|
setState({
|
|
@@ -171,6 +103,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
171
103
|
if (script.parentNode) {
|
|
172
104
|
script.parentNode.removeChild(script);
|
|
173
105
|
}
|
|
106
|
+
stopTamperingDetection();
|
|
174
107
|
};
|
|
175
108
|
}, [apiKey, config]);
|
|
176
109
|
const handleRetry = () => {
|
|
@@ -199,70 +132,229 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
199
132
|
if (fallback) {
|
|
200
133
|
return React.createElement(React.Fragment, null, fallback);
|
|
201
134
|
}
|
|
202
|
-
return (React.createElement("div", { style: styles.
|
|
135
|
+
return (React.createElement("div", { style: styles.errorContainer },
|
|
203
136
|
React.createElement("div", { style: styles.content },
|
|
204
137
|
React.createElement("div", { style: { ...styles.icon, color: '#ef4444' } },
|
|
205
138
|
React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
206
139
|
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
207
140
|
React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
208
141
|
React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" }))),
|
|
209
|
-
React.createElement("h2", { style: styles.
|
|
210
|
-
React.createElement("p", { style: styles.
|
|
211
|
-
React.createElement("
|
|
142
|
+
React.createElement("h2", { style: styles.errorTitle }, "Security Protection Required"),
|
|
143
|
+
React.createElement("p", { style: styles.errorMessage }, "This application requires Spektre security protection to run safely."),
|
|
144
|
+
React.createElement("p", { style: styles.errorDetails }, state.error || 'Unable to verify application security'),
|
|
145
|
+
React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry Loading"))));
|
|
212
146
|
}
|
|
213
147
|
return React.createElement(SpektreProvider, { value: state }, children);
|
|
214
148
|
};
|
|
149
|
+
// Tampering detection
|
|
150
|
+
let tamperingInterval = null;
|
|
151
|
+
let fetchIntegrityHash = null;
|
|
152
|
+
function startTamperingDetection(config) {
|
|
153
|
+
// Calculate integrity hash of fetch function
|
|
154
|
+
if (typeof window.fetch === 'function') {
|
|
155
|
+
fetchIntegrityHash = hashCode(window.fetch.toString());
|
|
156
|
+
}
|
|
157
|
+
tamperingInterval = window.setInterval(() => {
|
|
158
|
+
// Check 1: Verify JavaScript marker is still present
|
|
159
|
+
const jsEnabled = sessionStorage.getItem('spektre_js_enabled');
|
|
160
|
+
if (!jsEnabled) {
|
|
161
|
+
handleTampering('JavaScript marker removed', config);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// Check 2: Verify Spektre script is still in DOM
|
|
165
|
+
const scriptExists = document.querySelector('script[src*="scanner_client"]');
|
|
166
|
+
if (!scriptExists) {
|
|
167
|
+
handleTampering('Security script removed from page', config);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Check 3: Verify fetch function hasn't been tampered with
|
|
171
|
+
if (typeof window.fetch === 'function') {
|
|
172
|
+
const currentHash = hashCode(window.fetch.toString());
|
|
173
|
+
if (fetchIntegrityHash && currentHash !== fetchIntegrityHash) {
|
|
174
|
+
// Fetch function was modified
|
|
175
|
+
const fetchCode = window.fetch.toString();
|
|
176
|
+
// Check if it still has Spektre protection
|
|
177
|
+
if (!fetchCode.includes('Spektre') && !fetchCode.includes('PROTECTION')) {
|
|
178
|
+
handleTampering('Security protection has been disabled', config);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
handleTampering('Fetch function removed', config);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Check 4: Verify protection stats function exists
|
|
188
|
+
if (typeof window.getProtectionStats !== 'function') {
|
|
189
|
+
handleTampering('Security monitoring disabled', config);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}, 2000); // Check every 2 seconds
|
|
193
|
+
}
|
|
194
|
+
function stopTamperingDetection() {
|
|
195
|
+
if (tamperingInterval) {
|
|
196
|
+
clearInterval(tamperingInterval);
|
|
197
|
+
tamperingInterval = null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function handleTampering(reason, config) {
|
|
201
|
+
console.error('[Spektre SecurityGate] TAMPERING DETECTED:', reason);
|
|
202
|
+
// Stop checking to prevent infinite loops
|
|
203
|
+
stopTamperingDetection();
|
|
204
|
+
// Call callback if provided
|
|
205
|
+
if (config?.onTamperingDetected) {
|
|
206
|
+
config.onTamperingDetected(reason);
|
|
207
|
+
}
|
|
208
|
+
// Lock down the application
|
|
209
|
+
const root = document.getElementById('root');
|
|
210
|
+
if (root) {
|
|
211
|
+
root.innerHTML = '';
|
|
212
|
+
}
|
|
213
|
+
document.body.innerHTML = `
|
|
214
|
+
<div style="
|
|
215
|
+
position: fixed;
|
|
216
|
+
top: 0;
|
|
217
|
+
left: 0;
|
|
218
|
+
width: 100%;
|
|
219
|
+
height: 100%;
|
|
220
|
+
background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
|
|
221
|
+
color: white;
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
justify-content: center;
|
|
225
|
+
flex-direction: column;
|
|
226
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
227
|
+
z-index: 999999;
|
|
228
|
+
">
|
|
229
|
+
<div style="max-width: 500px; text-align: center; padding: 40px;">
|
|
230
|
+
<div style="font-size: 72px; margin-bottom: 24px;">⛔</div>
|
|
231
|
+
<h1 style="font-size: 28px; font-weight: 600; margin-bottom: 16px;">
|
|
232
|
+
Security Violation Detected
|
|
233
|
+
</h1>
|
|
234
|
+
<p style="font-size: 16px; line-height: 1.6; opacity: 0.9; margin-bottom: 24px;">
|
|
235
|
+
This application has been locked due to security tampering.
|
|
236
|
+
</p>
|
|
237
|
+
<div style="
|
|
238
|
+
background: rgba(255, 255, 255, 0.1);
|
|
239
|
+
border-radius: 8px;
|
|
240
|
+
padding: 16px;
|
|
241
|
+
margin-bottom: 24px;
|
|
242
|
+
font-size: 14px;
|
|
243
|
+
font-family: monospace;
|
|
244
|
+
">
|
|
245
|
+
${reason}
|
|
246
|
+
</div>
|
|
247
|
+
<button onclick="location.reload()" style="
|
|
248
|
+
padding: 12px 32px;
|
|
249
|
+
font-size: 16px;
|
|
250
|
+
font-weight: 500;
|
|
251
|
+
background: white;
|
|
252
|
+
color: #dc2626;
|
|
253
|
+
border: none;
|
|
254
|
+
border-radius: 8px;
|
|
255
|
+
cursor: pointer;
|
|
256
|
+
transition: transform 0.2s;
|
|
257
|
+
" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
|
|
258
|
+
Reload Application
|
|
259
|
+
</button>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
`;
|
|
263
|
+
}
|
|
264
|
+
// Simple hash function for integrity checking
|
|
265
|
+
function hashCode(str) {
|
|
266
|
+
let hash = 0;
|
|
267
|
+
for (let i = 0; i < str.length; i++) {
|
|
268
|
+
const char = str.charCodeAt(i);
|
|
269
|
+
hash = ((hash << 5) - hash) + char;
|
|
270
|
+
hash = hash & hash;
|
|
271
|
+
}
|
|
272
|
+
return hash.toString(36);
|
|
273
|
+
}
|
|
215
274
|
const styles = {
|
|
216
275
|
container: {
|
|
217
276
|
display: 'flex',
|
|
218
277
|
alignItems: 'center',
|
|
219
278
|
justifyContent: 'center',
|
|
220
279
|
minHeight: '100vh',
|
|
221
|
-
|
|
280
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
281
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
282
|
+
},
|
|
283
|
+
errorContainer: {
|
|
284
|
+
display: 'flex',
|
|
285
|
+
alignItems: 'center',
|
|
286
|
+
justifyContent: 'center',
|
|
287
|
+
minHeight: '100vh',
|
|
288
|
+
background: 'linear-gradient(135deg, #1f2937 0%, #111827 100%)',
|
|
222
289
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
223
290
|
},
|
|
224
291
|
content: {
|
|
225
292
|
textAlign: 'center',
|
|
226
293
|
padding: '2rem',
|
|
227
|
-
maxWidth: '
|
|
294
|
+
maxWidth: '500px',
|
|
295
|
+
background: 'rgba(255, 255, 255, 0.95)',
|
|
296
|
+
borderRadius: '16px',
|
|
297
|
+
boxShadow: '0 20px 60px rgba(0, 0, 0, 0.3)',
|
|
228
298
|
},
|
|
229
299
|
icon: {
|
|
230
|
-
color: '#
|
|
231
|
-
marginBottom: '
|
|
300
|
+
color: '#667eea',
|
|
301
|
+
marginBottom: '1.5rem',
|
|
232
302
|
display: 'flex',
|
|
233
303
|
justifyContent: 'center',
|
|
234
304
|
},
|
|
235
305
|
title: {
|
|
236
|
-
fontSize: '1.
|
|
306
|
+
fontSize: '1.75rem',
|
|
237
307
|
fontWeight: '600',
|
|
238
308
|
color: '#111827',
|
|
239
|
-
marginBottom: '0.
|
|
309
|
+
marginBottom: '0.75rem',
|
|
240
310
|
},
|
|
241
311
|
message: {
|
|
242
312
|
fontSize: '1rem',
|
|
243
313
|
color: '#6b7280',
|
|
244
314
|
marginBottom: '1.5rem',
|
|
245
|
-
lineHeight: '1.
|
|
315
|
+
lineHeight: '1.6',
|
|
316
|
+
},
|
|
317
|
+
errorTitle: {
|
|
318
|
+
fontSize: '1.75rem',
|
|
319
|
+
fontWeight: '600',
|
|
320
|
+
color: '#111827',
|
|
321
|
+
marginBottom: '0.75rem',
|
|
322
|
+
},
|
|
323
|
+
errorMessage: {
|
|
324
|
+
fontSize: '1rem',
|
|
325
|
+
color: '#6b7280',
|
|
326
|
+
marginBottom: '1rem',
|
|
327
|
+
lineHeight: '1.6',
|
|
328
|
+
},
|
|
329
|
+
errorDetails: {
|
|
330
|
+
fontSize: '0.875rem',
|
|
331
|
+
color: '#ef4444',
|
|
332
|
+
marginBottom: '1.5rem',
|
|
333
|
+
padding: '0.75rem',
|
|
334
|
+
background: '#fef2f2',
|
|
335
|
+
borderRadius: '8px',
|
|
336
|
+
fontFamily: 'monospace',
|
|
246
337
|
},
|
|
247
338
|
spinner: {
|
|
248
|
-
width: '
|
|
249
|
-
height: '
|
|
250
|
-
border: '
|
|
251
|
-
borderTopColor: '#
|
|
339
|
+
width: '40px',
|
|
340
|
+
height: '40px',
|
|
341
|
+
border: '4px solid rgba(255, 255, 255, 0.3)',
|
|
342
|
+
borderTopColor: '#667eea',
|
|
252
343
|
borderRadius: '50%',
|
|
253
344
|
margin: '0 auto',
|
|
254
345
|
animation: 'spin 1s linear infinite',
|
|
255
346
|
},
|
|
256
347
|
button: {
|
|
257
|
-
backgroundColor: '#
|
|
348
|
+
backgroundColor: '#667eea',
|
|
258
349
|
color: 'white',
|
|
259
350
|
border: 'none',
|
|
260
|
-
borderRadius: '
|
|
261
|
-
padding: '0.
|
|
351
|
+
borderRadius: '8px',
|
|
352
|
+
padding: '0.875rem 2rem',
|
|
262
353
|
fontSize: '1rem',
|
|
263
|
-
fontWeight: '
|
|
354
|
+
fontWeight: '600',
|
|
264
355
|
cursor: 'pointer',
|
|
265
|
-
transition: '
|
|
356
|
+
transition: 'all 0.2s',
|
|
357
|
+
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)',
|
|
266
358
|
},
|
|
267
359
|
};
|
|
268
360
|
const styleSheet = document.createElement('style');
|
|
@@ -275,11 +367,58 @@ styleSheet.textContent = `
|
|
|
275
367
|
`;
|
|
276
368
|
document.head.appendChild(styleSheet);
|
|
277
369
|
|
|
370
|
+
const useSpektre = () => {
|
|
371
|
+
const context = React.useContext(SpektreContext);
|
|
372
|
+
if (!context) {
|
|
373
|
+
throw new Error('useSpektre must be used within a SecurityGate component');
|
|
374
|
+
}
|
|
375
|
+
const runScan = async () => {
|
|
376
|
+
if (typeof window.securityScan === 'function') {
|
|
377
|
+
await window.securityScan();
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
const getTelemetry = () => {
|
|
381
|
+
if (typeof window.getSecurityTelemetry === 'function') {
|
|
382
|
+
return window.getSecurityTelemetry();
|
|
383
|
+
}
|
|
384
|
+
return context.monitoring;
|
|
385
|
+
};
|
|
386
|
+
const getProtectionStats = () => {
|
|
387
|
+
if (typeof window.getProtectionStats === 'function') {
|
|
388
|
+
return window.getProtectionStats();
|
|
389
|
+
}
|
|
390
|
+
return context.protection;
|
|
391
|
+
};
|
|
392
|
+
return {
|
|
393
|
+
isVerified: context.isVerified,
|
|
394
|
+
sessionId: context.sessionId,
|
|
395
|
+
protectionEnabled: context.protection?.enabled || false,
|
|
396
|
+
blockedRequests: context.protection?.blockedRequests || [],
|
|
397
|
+
totalBlocked: context.protection?.totalBlocked || 0,
|
|
398
|
+
secretExposures: context.monitoring?.secretExposures || 0,
|
|
399
|
+
scriptProfiles: context.monitoring?.scriptProfiles || 0,
|
|
400
|
+
supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
|
|
401
|
+
sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
|
|
402
|
+
runScan,
|
|
403
|
+
getTelemetry,
|
|
404
|
+
getProtectionStats,
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const useProtectedFetch = () => {
|
|
409
|
+
const { isVerified } = useSpektre();
|
|
410
|
+
const protectedFetch = async (url, options) => {
|
|
411
|
+
if (!isVerified) {
|
|
412
|
+
throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
|
|
413
|
+
}
|
|
414
|
+
return fetch(url, options);
|
|
415
|
+
};
|
|
416
|
+
return protectedFetch;
|
|
417
|
+
};
|
|
418
|
+
|
|
278
419
|
exports.SecurityGate = SecurityGate;
|
|
279
420
|
exports.SpektreContext = SpektreContext;
|
|
280
421
|
exports.SpektreProvider = SpektreProvider;
|
|
281
|
-
exports.VeilProvider = VeilProvider;
|
|
282
422
|
exports.useProtectedFetch = useProtectedFetch;
|
|
283
423
|
exports.useSpektre = useSpektre;
|
|
284
|
-
exports.useVeil = useVeil;
|
|
285
424
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
1
|
export interface SpektreConfig {
|
|
3
|
-
apiKey: string;
|
|
4
2
|
endpoint?: string;
|
|
5
|
-
environment?:
|
|
3
|
+
environment?: string;
|
|
6
4
|
enabledEnvironments?: string[];
|
|
7
5
|
modules?: {
|
|
8
6
|
performanceMonitoring?: boolean;
|
|
@@ -12,7 +10,7 @@ export interface SpektreConfig {
|
|
|
12
10
|
sessionProtection?: boolean;
|
|
13
11
|
activeProtection?: boolean;
|
|
14
12
|
};
|
|
15
|
-
onTamperingDetected?: (
|
|
13
|
+
onTamperingDetected?: (reason: string) => void;
|
|
16
14
|
onSecurityFailed?: (error: string) => void;
|
|
17
15
|
onAttackBlocked?: (attack: BlockedAttack) => void;
|
|
18
16
|
}
|
|
@@ -24,11 +22,22 @@ export interface SpektreState {
|
|
|
24
22
|
protection?: ProtectionState;
|
|
25
23
|
monitoring?: MonitoringState;
|
|
26
24
|
}
|
|
25
|
+
export interface VeilContextType {
|
|
26
|
+
isVerified: boolean;
|
|
27
|
+
isLoading: boolean;
|
|
28
|
+
error: string | null;
|
|
29
|
+
sessionId: string | null;
|
|
30
|
+
protection?: ProtectionState;
|
|
31
|
+
monitoring?: MonitoringState;
|
|
32
|
+
}
|
|
27
33
|
export interface ProtectionState {
|
|
28
34
|
enabled: boolean;
|
|
29
35
|
blockedRequests: BlockedRequest[];
|
|
30
36
|
totalBlocked: number;
|
|
31
37
|
}
|
|
38
|
+
export type VeilConfig = SpektreConfig;
|
|
39
|
+
export type VeilState = SpektreState;
|
|
40
|
+
export type VeilProps = SecurityGateProps;
|
|
32
41
|
export interface MonitoringState {
|
|
33
42
|
secretExposures: number;
|
|
34
43
|
scriptProfiles: number;
|
|
@@ -39,15 +48,14 @@ export interface BlockedRequest {
|
|
|
39
48
|
url: string;
|
|
40
49
|
reason: string;
|
|
41
50
|
timestamp: number;
|
|
42
|
-
severity
|
|
51
|
+
severity?: 'low' | 'medium' | 'high' | 'critical';
|
|
43
52
|
}
|
|
44
53
|
export interface BlockedAttack {
|
|
45
|
-
url: string;
|
|
46
|
-
reason: string;
|
|
47
|
-
timestamp: number;
|
|
48
|
-
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
49
54
|
type: string;
|
|
55
|
+
severity: string;
|
|
50
56
|
details: string;
|
|
57
|
+
timestamp: number;
|
|
58
|
+
url?: string;
|
|
51
59
|
}
|
|
52
60
|
export interface TamperingDetails {
|
|
53
61
|
type: string;
|
|
@@ -56,19 +64,8 @@ export interface TamperingDetails {
|
|
|
56
64
|
}
|
|
57
65
|
export interface SecurityGateProps {
|
|
58
66
|
apiKey: string;
|
|
59
|
-
children: ReactNode;
|
|
60
|
-
config?:
|
|
61
|
-
fallback?: ReactNode;
|
|
62
|
-
loadingComponent?: ReactNode;
|
|
63
|
-
}
|
|
64
|
-
export interface VeilConfig {
|
|
65
|
-
enableMonitoring?: boolean;
|
|
66
|
-
enableSecurityChecks?: boolean;
|
|
67
|
-
apiKey?: string;
|
|
68
|
-
environment?: 'development' | 'production';
|
|
69
|
-
}
|
|
70
|
-
export interface VeilContextType {
|
|
71
|
-
config: VeilConfig;
|
|
72
|
-
isMonitoring: boolean;
|
|
73
|
-
logEvent: (event: string, data?: Record<string, unknown>) => void;
|
|
67
|
+
children: React.ReactNode;
|
|
68
|
+
config?: SpektreConfig;
|
|
69
|
+
fallback?: React.ReactNode;
|
|
70
|
+
loadingComponent?: React.ReactNode;
|
|
74
71
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { VeilConfig, VeilContextType } from '../types';
|
|
3
|
-
export declare const VeilContext: React.Context<VeilContextType | undefined>;
|
|
4
|
-
interface VeilProviderProps {
|
|
5
|
-
config: VeilConfig;
|
|
6
|
-
children: React.ReactNode;
|
|
7
|
-
}
|
|
8
|
-
declare const VeilProvider: React.FC<VeilProviderProps>;
|
|
9
|
-
export default VeilProvider;
|
package/dist/hooks/useVeil.d.ts
DELETED