@spektre/veil 0.1.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/LICENSE +21 -0
- package/README.md +303 -0
- package/dist/SecurityGate.d.ts +3 -0
- package/dist/SpektreContext.d.ts +2 -0
- package/dist/SpektreProvider.d.ts +8 -0
- package/dist/components/VeilProvider.d.ts +9 -0
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/useProtectedFetch.d.ts +2 -0
- package/dist/hooks/useSpektre.d.ts +16 -0
- package/dist/hooks/useVeil.d.ts +2 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.esm.js +277 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +285 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +74 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Spektre React Package License
|
|
2
|
+
Copyright (c) 2025 Spektre.app
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted to any person obtaining a valid API key from
|
|
5
|
+
Spektre.app to use this software for the sole purpose of integrating with
|
|
6
|
+
the Spektre security platform.
|
|
7
|
+
|
|
8
|
+
RESTRICTIONS:
|
|
9
|
+
1. This software may only be used with a valid Spektre API key
|
|
10
|
+
2. Commercial use requires an active paid subscription to Spektre.app
|
|
11
|
+
3. Redistribution of this software is prohibited
|
|
12
|
+
4. Modification of this software is prohibited
|
|
13
|
+
5. Creation of derivative works is prohibited
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# @spektre/react
|
|
2
|
+
|
|
3
|
+
React security and monitoring wrapper for Spektre platform. Protect your React applications with real-time security scanning, monitoring, and active protection.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @spektre/veil
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Wrap your application with `SecurityGate` to enable security monitoring and protection:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { SecurityGate } from '@spektre/veil';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return (
|
|
20
|
+
<SecurityGate apiKey="your-spektre-api-key">
|
|
21
|
+
<YourApp />
|
|
22
|
+
</SecurityGate>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
That's it! Your app is now protected with Spektre security monitoring.
|
|
28
|
+
|
|
29
|
+
## Full Usage Example
|
|
30
|
+
|
|
31
|
+
Configure security modules and add custom handlers:
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { SecurityGate } from '@spektre/veil';
|
|
35
|
+
|
|
36
|
+
function App() {
|
|
37
|
+
return (
|
|
38
|
+
<SecurityGate
|
|
39
|
+
apiKey="your-spektre-api-key"
|
|
40
|
+
config={{
|
|
41
|
+
environment: 'prod',
|
|
42
|
+
enabledEnvironments: ['prod', 'staging'],
|
|
43
|
+
modules: {
|
|
44
|
+
performanceMonitoring: true,
|
|
45
|
+
secretDetection: true,
|
|
46
|
+
scriptProfiling: true,
|
|
47
|
+
supplyChainDetection: true,
|
|
48
|
+
sessionProtection: true,
|
|
49
|
+
activeProtection: true,
|
|
50
|
+
},
|
|
51
|
+
onSecurityFailed: (error) => {
|
|
52
|
+
console.error('Security verification failed:', error);
|
|
53
|
+
},
|
|
54
|
+
onAttackBlocked: (attack) => {
|
|
55
|
+
console.warn('Attack blocked:', attack);
|
|
56
|
+
},
|
|
57
|
+
onTamperingDetected: (details) => {
|
|
58
|
+
console.warn('Tampering detected:', details);
|
|
59
|
+
},
|
|
60
|
+
}}
|
|
61
|
+
loadingComponent={<CustomLoadingScreen />}
|
|
62
|
+
fallback={<SecurityErrorScreen />}
|
|
63
|
+
>
|
|
64
|
+
<YourApp />
|
|
65
|
+
</SecurityGate>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Using Hooks
|
|
71
|
+
|
|
72
|
+
### useSpektre Hook
|
|
73
|
+
|
|
74
|
+
Access security status and monitoring data throughout your application:
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { useSpektre } from '@spektre/veil';
|
|
78
|
+
|
|
79
|
+
function SecurityDashboard() {
|
|
80
|
+
const {
|
|
81
|
+
isVerified,
|
|
82
|
+
sessionId,
|
|
83
|
+
protectionEnabled,
|
|
84
|
+
blockedRequests,
|
|
85
|
+
totalBlocked,
|
|
86
|
+
secretExposures,
|
|
87
|
+
scriptProfiles,
|
|
88
|
+
supplyChainAlerts,
|
|
89
|
+
sessionAnomalies,
|
|
90
|
+
runScan,
|
|
91
|
+
getTelemetry,
|
|
92
|
+
getProtectionStats,
|
|
93
|
+
} = useSpektre();
|
|
94
|
+
|
|
95
|
+
const handleManualScan = async () => {
|
|
96
|
+
await runScan();
|
|
97
|
+
console.log('Security scan completed');
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div>
|
|
102
|
+
<h2>Security Status</h2>
|
|
103
|
+
<p>Verified: {isVerified ? 'Yes' : 'No'}</p>
|
|
104
|
+
<p>Session ID: {sessionId}</p>
|
|
105
|
+
<p>Protection: {protectionEnabled ? 'Active' : 'Inactive'}</p>
|
|
106
|
+
<p>Total Blocked Requests: {totalBlocked}</p>
|
|
107
|
+
<p>Secret Exposures: {secretExposures}</p>
|
|
108
|
+
<p>Script Profiles: {scriptProfiles}</p>
|
|
109
|
+
<p>Supply Chain Alerts: {supplyChainAlerts}</p>
|
|
110
|
+
<p>Session Anomalies: {sessionAnomalies}</p>
|
|
111
|
+
<button onClick={handleManualScan}>Run Security Scan</button>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### useProtectedFetch Hook
|
|
118
|
+
|
|
119
|
+
Make secure API calls that are only executed after security verification:
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { useProtectedFetch } from '@spektre/veil';
|
|
123
|
+
|
|
124
|
+
function DataComponent() {
|
|
125
|
+
const fetch = useProtectedFetch();
|
|
126
|
+
const [data, setData] = useState(null);
|
|
127
|
+
|
|
128
|
+
const loadData = async () => {
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch('/api/sensitive-data');
|
|
131
|
+
const json = await response.json();
|
|
132
|
+
setData(json);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error('Fetch failed:', error);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<div>
|
|
140
|
+
<button onClick={loadData}>Load Data</button>
|
|
141
|
+
{data && <pre>{JSON.stringify(data, null, 2)}</pre>}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## API Reference
|
|
148
|
+
|
|
149
|
+
### SecurityGate Component
|
|
150
|
+
|
|
151
|
+
The main component that wraps your application and provides security monitoring.
|
|
152
|
+
|
|
153
|
+
#### Props
|
|
154
|
+
|
|
155
|
+
| Prop | Type | Required | Description |
|
|
156
|
+
|------|------|----------|-------------|
|
|
157
|
+
| `apiKey` | `string` | Yes | Your Spektre API key from the dashboard |
|
|
158
|
+
| `children` | `ReactNode` | Yes | Your application components |
|
|
159
|
+
| `config` | `SpektreConfig` | No | Configuration options (see below) |
|
|
160
|
+
| `fallback` | `ReactNode` | No | Custom component to show on security failure |
|
|
161
|
+
| `loadingComponent` | `ReactNode` | No | Custom component to show during initialization |
|
|
162
|
+
|
|
163
|
+
#### Config Options
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
interface SpektreConfig {
|
|
167
|
+
// Environment settings
|
|
168
|
+
environment?: 'dev' | 'staging' | 'prod';
|
|
169
|
+
enabledEnvironments?: string[];
|
|
170
|
+
|
|
171
|
+
// Security modules
|
|
172
|
+
modules?: {
|
|
173
|
+
performanceMonitoring?: boolean;
|
|
174
|
+
secretDetection?: boolean;
|
|
175
|
+
scriptProfiling?: boolean;
|
|
176
|
+
supplyChainDetection?: boolean;
|
|
177
|
+
sessionProtection?: boolean;
|
|
178
|
+
activeProtection?: boolean;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Event handlers
|
|
182
|
+
onSecurityFailed?: (error: string) => void;
|
|
183
|
+
onAttackBlocked?: (attack: BlockedAttack) => void;
|
|
184
|
+
onTamperingDetected?: (details: TamperingDetails) => void;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### useSpektre Hook
|
|
189
|
+
|
|
190
|
+
Returns security status and monitoring data.
|
|
191
|
+
|
|
192
|
+
#### Return Values
|
|
193
|
+
|
|
194
|
+
| Property | Type | Description |
|
|
195
|
+
|----------|------|-------------|
|
|
196
|
+
| `isVerified` | `boolean` | Whether security verification passed |
|
|
197
|
+
| `sessionId` | `string \| null` | Current Spektre session ID |
|
|
198
|
+
| `protectionEnabled` | `boolean` | Whether active protection is enabled |
|
|
199
|
+
| `blockedRequests` | `BlockedRequest[]` | List of blocked malicious requests |
|
|
200
|
+
| `totalBlocked` | `number` | Total count of blocked requests |
|
|
201
|
+
| `secretExposures` | `number` | Number of detected secret exposures |
|
|
202
|
+
| `scriptProfiles` | `number` | Number of profiled scripts |
|
|
203
|
+
| `supplyChainAlerts` | `number` | Number of supply chain alerts |
|
|
204
|
+
| `sessionAnomalies` | `number` | Number of session anomalies detected |
|
|
205
|
+
| `runScan` | `() => Promise<void>` | Manually trigger a security scan |
|
|
206
|
+
| `getTelemetry` | `() => MonitoringState` | Get current monitoring telemetry |
|
|
207
|
+
| `getProtectionStats` | `() => ProtectionState` | Get current protection statistics |
|
|
208
|
+
|
|
209
|
+
### useProtectedFetch Hook
|
|
210
|
+
|
|
211
|
+
Returns a fetch function that only executes after security verification.
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
const fetch: ProtectedFetch = useProtectedFetch();
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The returned `fetch` function has the same signature as the native `fetch` API but throws an error if called before security verification is complete.
|
|
218
|
+
|
|
219
|
+
## Security Modules
|
|
220
|
+
|
|
221
|
+
### Performance Monitoring
|
|
222
|
+
Tracks application performance metrics and identifies performance anomalies that could indicate security issues.
|
|
223
|
+
|
|
224
|
+
### Secret Detection
|
|
225
|
+
Scans for exposed API keys, tokens, and other sensitive credentials in your application code and network requests.
|
|
226
|
+
|
|
227
|
+
### Script Profiling
|
|
228
|
+
Analyzes all scripts loaded by your application to detect malicious or suspicious code.
|
|
229
|
+
|
|
230
|
+
### Supply Chain Detection
|
|
231
|
+
Monitors third-party dependencies and detects compromised or vulnerable packages.
|
|
232
|
+
|
|
233
|
+
### Session Protection
|
|
234
|
+
Protects user sessions from hijacking, fixation, and other session-based attacks.
|
|
235
|
+
|
|
236
|
+
### Active Protection
|
|
237
|
+
Actively blocks malicious requests and attacks in real-time.
|
|
238
|
+
|
|
239
|
+
## Environment Configuration
|
|
240
|
+
|
|
241
|
+
Control when security monitoring is active:
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
<SecurityGate
|
|
245
|
+
apiKey="your-api-key"
|
|
246
|
+
config={{
|
|
247
|
+
environment: 'prod',
|
|
248
|
+
enabledEnvironments: ['prod', 'staging'],
|
|
249
|
+
}}
|
|
250
|
+
>
|
|
251
|
+
<App />
|
|
252
|
+
</SecurityGate>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
In this example, security monitoring only runs in production and staging environments. In other environments (like development), the SecurityGate passes through without performing security checks.
|
|
256
|
+
|
|
257
|
+
## Custom UI Components
|
|
258
|
+
|
|
259
|
+
### Custom Loading Screen
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
<SecurityGate
|
|
263
|
+
apiKey="your-api-key"
|
|
264
|
+
loadingComponent={
|
|
265
|
+
<div className="loading-screen">
|
|
266
|
+
<Spinner />
|
|
267
|
+
<p>Initializing security...</p>
|
|
268
|
+
</div>
|
|
269
|
+
}
|
|
270
|
+
>
|
|
271
|
+
<App />
|
|
272
|
+
</SecurityGate>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Custom Error Fallback
|
|
276
|
+
|
|
277
|
+
```tsx
|
|
278
|
+
<SecurityGate
|
|
279
|
+
apiKey="your-api-key"
|
|
280
|
+
fallback={
|
|
281
|
+
<div className="error-screen">
|
|
282
|
+
<h1>Security Verification Failed</h1>
|
|
283
|
+
<p>Please contact support</p>
|
|
284
|
+
</div>
|
|
285
|
+
}
|
|
286
|
+
>
|
|
287
|
+
<App />
|
|
288
|
+
</SecurityGate>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Links
|
|
292
|
+
|
|
293
|
+
- [Spektre Platform](https://spektre.io) - Main platform website
|
|
294
|
+
- [Dashboard](https://dashboard.spektre.io) - Manage your API keys and view security reports
|
|
295
|
+
- [Documentation](https://docs.spektre.io) - Complete documentation and guides
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
Built with Spektre - Securing the future of web applications
|
|
@@ -0,0 +1,9 @@
|
|
|
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;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProtectionState, MonitoringState } from '../types';
|
|
2
|
+
export interface UseSpektreReturn {
|
|
3
|
+
isVerified: boolean;
|
|
4
|
+
sessionId: string | null;
|
|
5
|
+
protectionEnabled: boolean;
|
|
6
|
+
blockedRequests: ProtectionState['blockedRequests'];
|
|
7
|
+
totalBlocked: number;
|
|
8
|
+
secretExposures: number;
|
|
9
|
+
scriptProfiles: number;
|
|
10
|
+
supplyChainAlerts: number;
|
|
11
|
+
sessionAnomalies: number;
|
|
12
|
+
runScan: () => Promise<void>;
|
|
13
|
+
getTelemetry: () => MonitoringState | undefined;
|
|
14
|
+
getProtectionStats: () => ProtectionState | undefined;
|
|
15
|
+
}
|
|
16
|
+
export declare const useSpektre: () => UseSpektreReturn;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export { SecurityGate } from './SecurityGate';
|
|
6
|
+
export type { SpektreConfig, SpektreState, ProtectionState, MonitoringState, BlockedRequest, BlockedAttack, TamperingDetails, SecurityGateProps, VeilConfig, VeilContextType, } from './types';
|
|
7
|
+
export type { UseSpektreReturn, ProtectedFetch } from './hooks';
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import React, { createContext, useMemo, useCallback, useContext, useState, useEffect } from 'react';
|
|
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
|
+
};
|
|
18
|
+
|
|
19
|
+
const SpektreContext = createContext(null);
|
|
20
|
+
SpektreContext.displayName = 'SpektreContext';
|
|
21
|
+
|
|
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
|
+
const SpektreProvider = ({ value, children }) => {
|
|
80
|
+
return React.createElement(SpektreContext.Provider, { value: value }, children);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const SUPABASE_BASE_URL = 'https://vevqxlmcrltcxygmlomv.supabase.co';
|
|
84
|
+
const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, }) => {
|
|
85
|
+
const [state, setState] = useState({
|
|
86
|
+
isVerified: false,
|
|
87
|
+
isLoading: true,
|
|
88
|
+
error: null,
|
|
89
|
+
sessionId: null,
|
|
90
|
+
});
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const scriptUrl = `${SUPABASE_BASE_URL}/functions/v1/scanner_client`;
|
|
93
|
+
const script = document.createElement('script');
|
|
94
|
+
script.src = `${scriptUrl}?apiKey=${encodeURIComponent(apiKey)}`;
|
|
95
|
+
script.type = 'module';
|
|
96
|
+
script.setAttribute('data-public-key', apiKey);
|
|
97
|
+
script.setAttribute('data-endpoint', `${SUPABASE_BASE_URL}/functions/v1/monitoring_receiver`);
|
|
98
|
+
script.setAttribute('data-config-endpoint', `${SUPABASE_BASE_URL}/functions/v1/scanner_config`);
|
|
99
|
+
script.setAttribute('data-env', config?.environment || 'prod');
|
|
100
|
+
script.setAttribute('data-auto-scan', 'true');
|
|
101
|
+
if (config?.enabledEnvironments && config.enabledEnvironments.length > 0) {
|
|
102
|
+
script.setAttribute('data-enabled-envs', config.enabledEnvironments.join(','));
|
|
103
|
+
}
|
|
104
|
+
if (config?.modules) {
|
|
105
|
+
if (config.modules.performanceMonitoring !== undefined) {
|
|
106
|
+
script.setAttribute('data-perf', String(config.modules.performanceMonitoring));
|
|
107
|
+
}
|
|
108
|
+
if (config.modules.secretDetection !== undefined) {
|
|
109
|
+
script.setAttribute('data-secrets', String(config.modules.secretDetection));
|
|
110
|
+
}
|
|
111
|
+
if (config.modules.scriptProfiling !== undefined) {
|
|
112
|
+
script.setAttribute('data-scripts', String(config.modules.scriptProfiling));
|
|
113
|
+
}
|
|
114
|
+
if (config.modules.supplyChainDetection !== undefined) {
|
|
115
|
+
script.setAttribute('data-supply-chain', String(config.modules.supplyChainDetection));
|
|
116
|
+
}
|
|
117
|
+
if (config.modules.sessionProtection !== undefined) {
|
|
118
|
+
script.setAttribute('data-session', String(config.modules.sessionProtection));
|
|
119
|
+
}
|
|
120
|
+
if (config.modules.activeProtection !== undefined) {
|
|
121
|
+
script.setAttribute('data-active', String(config.modules.activeProtection));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
script.onload = () => {
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
try {
|
|
127
|
+
const sessionId = sessionStorage.getItem('spektre_session_id');
|
|
128
|
+
let protection;
|
|
129
|
+
if (typeof window.getProtectionStats === 'function') {
|
|
130
|
+
protection = window.getProtectionStats();
|
|
131
|
+
}
|
|
132
|
+
let monitoring;
|
|
133
|
+
if (typeof window.getSecurityTelemetry === 'function') {
|
|
134
|
+
monitoring = window.getSecurityTelemetry();
|
|
135
|
+
}
|
|
136
|
+
setState({
|
|
137
|
+
isVerified: true,
|
|
138
|
+
isLoading: false,
|
|
139
|
+
error: null,
|
|
140
|
+
sessionId,
|
|
141
|
+
protection,
|
|
142
|
+
monitoring,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
setState({
|
|
147
|
+
isVerified: false,
|
|
148
|
+
isLoading: false,
|
|
149
|
+
error: err instanceof Error ? err.message : 'Failed to initialize security',
|
|
150
|
+
sessionId: null,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}, 500);
|
|
154
|
+
};
|
|
155
|
+
script.onerror = () => {
|
|
156
|
+
const errorMessage = 'Failed to load security script';
|
|
157
|
+
setState({
|
|
158
|
+
isVerified: false,
|
|
159
|
+
isLoading: false,
|
|
160
|
+
error: errorMessage,
|
|
161
|
+
sessionId: null,
|
|
162
|
+
});
|
|
163
|
+
if (config?.onSecurityFailed) {
|
|
164
|
+
config.onSecurityFailed(errorMessage);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
document.head.appendChild(script);
|
|
168
|
+
return () => {
|
|
169
|
+
if (script.parentNode) {
|
|
170
|
+
script.parentNode.removeChild(script);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}, [apiKey, config]);
|
|
174
|
+
const handleRetry = () => {
|
|
175
|
+
setState({
|
|
176
|
+
isVerified: false,
|
|
177
|
+
isLoading: true,
|
|
178
|
+
error: null,
|
|
179
|
+
sessionId: null,
|
|
180
|
+
});
|
|
181
|
+
window.location.reload();
|
|
182
|
+
};
|
|
183
|
+
if (state.isLoading) {
|
|
184
|
+
if (loadingComponent) {
|
|
185
|
+
return React.createElement(React.Fragment, null, loadingComponent);
|
|
186
|
+
}
|
|
187
|
+
return (React.createElement("div", { style: styles.container },
|
|
188
|
+
React.createElement("div", { style: styles.content },
|
|
189
|
+
React.createElement("div", { style: styles.icon },
|
|
190
|
+
React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
191
|
+
React.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }))),
|
|
192
|
+
React.createElement("h2", { style: styles.title }, "Initializing Security"),
|
|
193
|
+
React.createElement("p", { style: styles.message }, "Please wait while we verify your application..."),
|
|
194
|
+
React.createElement("div", { style: styles.spinner }))));
|
|
195
|
+
}
|
|
196
|
+
if (state.error || !state.isVerified) {
|
|
197
|
+
if (fallback) {
|
|
198
|
+
return React.createElement(React.Fragment, null, fallback);
|
|
199
|
+
}
|
|
200
|
+
return (React.createElement("div", { style: styles.container },
|
|
201
|
+
React.createElement("div", { style: styles.content },
|
|
202
|
+
React.createElement("div", { style: { ...styles.icon, color: '#ef4444' } },
|
|
203
|
+
React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
204
|
+
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
205
|
+
React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
206
|
+
React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" }))),
|
|
207
|
+
React.createElement("h2", { style: styles.title }, "Security Verification Failed"),
|
|
208
|
+
React.createElement("p", { style: styles.message }, state.error || 'Unable to verify application security'),
|
|
209
|
+
React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry"))));
|
|
210
|
+
}
|
|
211
|
+
return React.createElement(SpektreProvider, { value: state }, children);
|
|
212
|
+
};
|
|
213
|
+
const styles = {
|
|
214
|
+
container: {
|
|
215
|
+
display: 'flex',
|
|
216
|
+
alignItems: 'center',
|
|
217
|
+
justifyContent: 'center',
|
|
218
|
+
minHeight: '100vh',
|
|
219
|
+
backgroundColor: '#f9fafb',
|
|
220
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
221
|
+
},
|
|
222
|
+
content: {
|
|
223
|
+
textAlign: 'center',
|
|
224
|
+
padding: '2rem',
|
|
225
|
+
maxWidth: '400px',
|
|
226
|
+
},
|
|
227
|
+
icon: {
|
|
228
|
+
color: '#3b82f6',
|
|
229
|
+
marginBottom: '1rem',
|
|
230
|
+
display: 'flex',
|
|
231
|
+
justifyContent: 'center',
|
|
232
|
+
},
|
|
233
|
+
title: {
|
|
234
|
+
fontSize: '1.5rem',
|
|
235
|
+
fontWeight: '600',
|
|
236
|
+
color: '#111827',
|
|
237
|
+
marginBottom: '0.5rem',
|
|
238
|
+
},
|
|
239
|
+
message: {
|
|
240
|
+
fontSize: '1rem',
|
|
241
|
+
color: '#6b7280',
|
|
242
|
+
marginBottom: '1.5rem',
|
|
243
|
+
lineHeight: '1.5',
|
|
244
|
+
},
|
|
245
|
+
spinner: {
|
|
246
|
+
width: '32px',
|
|
247
|
+
height: '32px',
|
|
248
|
+
border: '3px solid #e5e7eb',
|
|
249
|
+
borderTopColor: '#3b82f6',
|
|
250
|
+
borderRadius: '50%',
|
|
251
|
+
margin: '0 auto',
|
|
252
|
+
animation: 'spin 1s linear infinite',
|
|
253
|
+
},
|
|
254
|
+
button: {
|
|
255
|
+
backgroundColor: '#3b82f6',
|
|
256
|
+
color: 'white',
|
|
257
|
+
border: 'none',
|
|
258
|
+
borderRadius: '0.5rem',
|
|
259
|
+
padding: '0.75rem 1.5rem',
|
|
260
|
+
fontSize: '1rem',
|
|
261
|
+
fontWeight: '500',
|
|
262
|
+
cursor: 'pointer',
|
|
263
|
+
transition: 'background-color 0.2s',
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
const styleSheet = document.createElement('style');
|
|
267
|
+
styleSheet.textContent = `
|
|
268
|
+
@keyframes spin {
|
|
269
|
+
to {
|
|
270
|
+
transform: rotate(360deg);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
`;
|
|
274
|
+
document.head.appendChild(styleSheet);
|
|
275
|
+
|
|
276
|
+
export { SecurityGate, SpektreContext, SpektreProvider, VeilProvider, useProtectedFetch, useSpektre, useVeil };
|
|
277
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
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
|
+
const SpektreContext = React.createContext(null);
|
|
22
|
+
SpektreContext.displayName = 'SpektreContext';
|
|
23
|
+
|
|
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
|
+
const SpektreProvider = ({ value, children }) => {
|
|
82
|
+
return React.createElement(SpektreContext.Provider, { value: value }, children);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const SUPABASE_BASE_URL = 'https://vevqxlmcrltcxygmlomv.supabase.co';
|
|
86
|
+
const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, }) => {
|
|
87
|
+
const [state, setState] = React.useState({
|
|
88
|
+
isVerified: false,
|
|
89
|
+
isLoading: true,
|
|
90
|
+
error: null,
|
|
91
|
+
sessionId: null,
|
|
92
|
+
});
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
const scriptUrl = `${SUPABASE_BASE_URL}/functions/v1/scanner_client`;
|
|
95
|
+
const script = document.createElement('script');
|
|
96
|
+
script.src = `${scriptUrl}?apiKey=${encodeURIComponent(apiKey)}`;
|
|
97
|
+
script.type = 'module';
|
|
98
|
+
script.setAttribute('data-public-key', apiKey);
|
|
99
|
+
script.setAttribute('data-endpoint', `${SUPABASE_BASE_URL}/functions/v1/monitoring_receiver`);
|
|
100
|
+
script.setAttribute('data-config-endpoint', `${SUPABASE_BASE_URL}/functions/v1/scanner_config`);
|
|
101
|
+
script.setAttribute('data-env', config?.environment || 'prod');
|
|
102
|
+
script.setAttribute('data-auto-scan', 'true');
|
|
103
|
+
if (config?.enabledEnvironments && config.enabledEnvironments.length > 0) {
|
|
104
|
+
script.setAttribute('data-enabled-envs', config.enabledEnvironments.join(','));
|
|
105
|
+
}
|
|
106
|
+
if (config?.modules) {
|
|
107
|
+
if (config.modules.performanceMonitoring !== undefined) {
|
|
108
|
+
script.setAttribute('data-perf', String(config.modules.performanceMonitoring));
|
|
109
|
+
}
|
|
110
|
+
if (config.modules.secretDetection !== undefined) {
|
|
111
|
+
script.setAttribute('data-secrets', String(config.modules.secretDetection));
|
|
112
|
+
}
|
|
113
|
+
if (config.modules.scriptProfiling !== undefined) {
|
|
114
|
+
script.setAttribute('data-scripts', String(config.modules.scriptProfiling));
|
|
115
|
+
}
|
|
116
|
+
if (config.modules.supplyChainDetection !== undefined) {
|
|
117
|
+
script.setAttribute('data-supply-chain', String(config.modules.supplyChainDetection));
|
|
118
|
+
}
|
|
119
|
+
if (config.modules.sessionProtection !== undefined) {
|
|
120
|
+
script.setAttribute('data-session', String(config.modules.sessionProtection));
|
|
121
|
+
}
|
|
122
|
+
if (config.modules.activeProtection !== undefined) {
|
|
123
|
+
script.setAttribute('data-active', String(config.modules.activeProtection));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
script.onload = () => {
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
try {
|
|
129
|
+
const sessionId = sessionStorage.getItem('spektre_session_id');
|
|
130
|
+
let protection;
|
|
131
|
+
if (typeof window.getProtectionStats === 'function') {
|
|
132
|
+
protection = window.getProtectionStats();
|
|
133
|
+
}
|
|
134
|
+
let monitoring;
|
|
135
|
+
if (typeof window.getSecurityTelemetry === 'function') {
|
|
136
|
+
monitoring = window.getSecurityTelemetry();
|
|
137
|
+
}
|
|
138
|
+
setState({
|
|
139
|
+
isVerified: true,
|
|
140
|
+
isLoading: false,
|
|
141
|
+
error: null,
|
|
142
|
+
sessionId,
|
|
143
|
+
protection,
|
|
144
|
+
monitoring,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
setState({
|
|
149
|
+
isVerified: false,
|
|
150
|
+
isLoading: false,
|
|
151
|
+
error: err instanceof Error ? err.message : 'Failed to initialize security',
|
|
152
|
+
sessionId: null,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}, 500);
|
|
156
|
+
};
|
|
157
|
+
script.onerror = () => {
|
|
158
|
+
const errorMessage = 'Failed to load security script';
|
|
159
|
+
setState({
|
|
160
|
+
isVerified: false,
|
|
161
|
+
isLoading: false,
|
|
162
|
+
error: errorMessage,
|
|
163
|
+
sessionId: null,
|
|
164
|
+
});
|
|
165
|
+
if (config?.onSecurityFailed) {
|
|
166
|
+
config.onSecurityFailed(errorMessage);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
document.head.appendChild(script);
|
|
170
|
+
return () => {
|
|
171
|
+
if (script.parentNode) {
|
|
172
|
+
script.parentNode.removeChild(script);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}, [apiKey, config]);
|
|
176
|
+
const handleRetry = () => {
|
|
177
|
+
setState({
|
|
178
|
+
isVerified: false,
|
|
179
|
+
isLoading: true,
|
|
180
|
+
error: null,
|
|
181
|
+
sessionId: null,
|
|
182
|
+
});
|
|
183
|
+
window.location.reload();
|
|
184
|
+
};
|
|
185
|
+
if (state.isLoading) {
|
|
186
|
+
if (loadingComponent) {
|
|
187
|
+
return React.createElement(React.Fragment, null, loadingComponent);
|
|
188
|
+
}
|
|
189
|
+
return (React.createElement("div", { style: styles.container },
|
|
190
|
+
React.createElement("div", { style: styles.content },
|
|
191
|
+
React.createElement("div", { style: styles.icon },
|
|
192
|
+
React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
193
|
+
React.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }))),
|
|
194
|
+
React.createElement("h2", { style: styles.title }, "Initializing Security"),
|
|
195
|
+
React.createElement("p", { style: styles.message }, "Please wait while we verify your application..."),
|
|
196
|
+
React.createElement("div", { style: styles.spinner }))));
|
|
197
|
+
}
|
|
198
|
+
if (state.error || !state.isVerified) {
|
|
199
|
+
if (fallback) {
|
|
200
|
+
return React.createElement(React.Fragment, null, fallback);
|
|
201
|
+
}
|
|
202
|
+
return (React.createElement("div", { style: styles.container },
|
|
203
|
+
React.createElement("div", { style: styles.content },
|
|
204
|
+
React.createElement("div", { style: { ...styles.icon, color: '#ef4444' } },
|
|
205
|
+
React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
206
|
+
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
207
|
+
React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
208
|
+
React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" }))),
|
|
209
|
+
React.createElement("h2", { style: styles.title }, "Security Verification Failed"),
|
|
210
|
+
React.createElement("p", { style: styles.message }, state.error || 'Unable to verify application security'),
|
|
211
|
+
React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry"))));
|
|
212
|
+
}
|
|
213
|
+
return React.createElement(SpektreProvider, { value: state }, children);
|
|
214
|
+
};
|
|
215
|
+
const styles = {
|
|
216
|
+
container: {
|
|
217
|
+
display: 'flex',
|
|
218
|
+
alignItems: 'center',
|
|
219
|
+
justifyContent: 'center',
|
|
220
|
+
minHeight: '100vh',
|
|
221
|
+
backgroundColor: '#f9fafb',
|
|
222
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
223
|
+
},
|
|
224
|
+
content: {
|
|
225
|
+
textAlign: 'center',
|
|
226
|
+
padding: '2rem',
|
|
227
|
+
maxWidth: '400px',
|
|
228
|
+
},
|
|
229
|
+
icon: {
|
|
230
|
+
color: '#3b82f6',
|
|
231
|
+
marginBottom: '1rem',
|
|
232
|
+
display: 'flex',
|
|
233
|
+
justifyContent: 'center',
|
|
234
|
+
},
|
|
235
|
+
title: {
|
|
236
|
+
fontSize: '1.5rem',
|
|
237
|
+
fontWeight: '600',
|
|
238
|
+
color: '#111827',
|
|
239
|
+
marginBottom: '0.5rem',
|
|
240
|
+
},
|
|
241
|
+
message: {
|
|
242
|
+
fontSize: '1rem',
|
|
243
|
+
color: '#6b7280',
|
|
244
|
+
marginBottom: '1.5rem',
|
|
245
|
+
lineHeight: '1.5',
|
|
246
|
+
},
|
|
247
|
+
spinner: {
|
|
248
|
+
width: '32px',
|
|
249
|
+
height: '32px',
|
|
250
|
+
border: '3px solid #e5e7eb',
|
|
251
|
+
borderTopColor: '#3b82f6',
|
|
252
|
+
borderRadius: '50%',
|
|
253
|
+
margin: '0 auto',
|
|
254
|
+
animation: 'spin 1s linear infinite',
|
|
255
|
+
},
|
|
256
|
+
button: {
|
|
257
|
+
backgroundColor: '#3b82f6',
|
|
258
|
+
color: 'white',
|
|
259
|
+
border: 'none',
|
|
260
|
+
borderRadius: '0.5rem',
|
|
261
|
+
padding: '0.75rem 1.5rem',
|
|
262
|
+
fontSize: '1rem',
|
|
263
|
+
fontWeight: '500',
|
|
264
|
+
cursor: 'pointer',
|
|
265
|
+
transition: 'background-color 0.2s',
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
const styleSheet = document.createElement('style');
|
|
269
|
+
styleSheet.textContent = `
|
|
270
|
+
@keyframes spin {
|
|
271
|
+
to {
|
|
272
|
+
transform: rotate(360deg);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
`;
|
|
276
|
+
document.head.appendChild(styleSheet);
|
|
277
|
+
|
|
278
|
+
exports.SecurityGate = SecurityGate;
|
|
279
|
+
exports.SpektreContext = SpektreContext;
|
|
280
|
+
exports.SpektreProvider = SpektreProvider;
|
|
281
|
+
exports.VeilProvider = VeilProvider;
|
|
282
|
+
exports.useProtectedFetch = useProtectedFetch;
|
|
283
|
+
exports.useSpektre = useSpektre;
|
|
284
|
+
exports.useVeil = useVeil;
|
|
285
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface SpektreConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
environment?: 'dev' | 'staging' | 'prod';
|
|
6
|
+
enabledEnvironments?: string[];
|
|
7
|
+
modules?: {
|
|
8
|
+
performanceMonitoring?: boolean;
|
|
9
|
+
secretDetection?: boolean;
|
|
10
|
+
scriptProfiling?: boolean;
|
|
11
|
+
supplyChainDetection?: boolean;
|
|
12
|
+
sessionProtection?: boolean;
|
|
13
|
+
activeProtection?: boolean;
|
|
14
|
+
};
|
|
15
|
+
onTamperingDetected?: (details: TamperingDetails) => void;
|
|
16
|
+
onSecurityFailed?: (error: string) => void;
|
|
17
|
+
onAttackBlocked?: (attack: BlockedAttack) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface SpektreState {
|
|
20
|
+
isVerified: boolean;
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
error: string | null;
|
|
23
|
+
sessionId: string | null;
|
|
24
|
+
protection?: ProtectionState;
|
|
25
|
+
monitoring?: MonitoringState;
|
|
26
|
+
}
|
|
27
|
+
export interface ProtectionState {
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
blockedRequests: BlockedRequest[];
|
|
30
|
+
totalBlocked: number;
|
|
31
|
+
}
|
|
32
|
+
export interface MonitoringState {
|
|
33
|
+
secretExposures: number;
|
|
34
|
+
scriptProfiles: number;
|
|
35
|
+
supplyChainAlerts: number;
|
|
36
|
+
sessionAnomalies: number;
|
|
37
|
+
}
|
|
38
|
+
export interface BlockedRequest {
|
|
39
|
+
url: string;
|
|
40
|
+
reason: string;
|
|
41
|
+
timestamp: number;
|
|
42
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
43
|
+
}
|
|
44
|
+
export interface BlockedAttack {
|
|
45
|
+
url: string;
|
|
46
|
+
reason: string;
|
|
47
|
+
timestamp: number;
|
|
48
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
49
|
+
type: string;
|
|
50
|
+
details: string;
|
|
51
|
+
}
|
|
52
|
+
export interface TamperingDetails {
|
|
53
|
+
type: string;
|
|
54
|
+
detected: boolean;
|
|
55
|
+
timestamp: number;
|
|
56
|
+
}
|
|
57
|
+
export interface SecurityGateProps {
|
|
58
|
+
apiKey: string;
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
config?: Partial<SpektreConfig>;
|
|
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;
|
|
74
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spektre/veil",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Security and monitoring wrapper for React apps built with AI tools",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "rollup -c",
|
|
15
|
+
"dev": "rollup -c -w",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": ">=16.8.0 || ^17.0.0 || ^18.0.0",
|
|
21
|
+
"react-dom": ">=16.8.0 || ^17.0.0 || ^18.0.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@eslint/js": "^9.9.1",
|
|
25
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
26
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
27
|
+
"@types/react": "^18.3.5",
|
|
28
|
+
"@types/react-dom": "^18.3.0",
|
|
29
|
+
"eslint": "^9.9.1",
|
|
30
|
+
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
|
31
|
+
"globals": "^15.9.0",
|
|
32
|
+
"rollup": "^4.9.6",
|
|
33
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
34
|
+
"rollup-plugin-typescript2": "^0.36.0",
|
|
35
|
+
"typescript": "^5.5.3",
|
|
36
|
+
"typescript-eslint": "^8.3.0"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"react",
|
|
40
|
+
"security",
|
|
41
|
+
"monitoring",
|
|
42
|
+
"ai",
|
|
43
|
+
"wrapper"
|
|
44
|
+
],
|
|
45
|
+
"author": "Spektre.app",
|
|
46
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
47
|
+
"homepage": "https://spektre.io",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/spektre-io/veil/issues"
|
|
50
|
+
}
|
|
51
|
+
}
|