@ceon-oy/monitor-sdk 1.0.6 → 1.0.9
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/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +68 -52
- package/dist/index.mjs +68 -52
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -142,6 +142,7 @@ declare class MonitorClient {
|
|
|
142
142
|
private settingsPollingTimer;
|
|
143
143
|
private lastScanTime;
|
|
144
144
|
private lastKnownScanRequestedAt;
|
|
145
|
+
private lastKnownTechScanRequestedAt;
|
|
145
146
|
constructor(config: MonitorClientConfig);
|
|
146
147
|
captureError(error: Error, context?: ErrorContext): Promise<void>;
|
|
147
148
|
captureMessage(message: string, severity?: Severity, context?: ErrorContext): Promise<void>;
|
|
@@ -151,12 +152,13 @@ declare class MonitorClient {
|
|
|
151
152
|
private stopAuditIntervalTimer;
|
|
152
153
|
/**
|
|
153
154
|
* Fetch project settings from the monitoring server.
|
|
154
|
-
* Returns configuration including vulnerability scan interval and scan request
|
|
155
|
+
* Returns configuration including vulnerability scan interval and scan request timestamps.
|
|
155
156
|
*/
|
|
156
157
|
fetchProjectSettings(): Promise<{
|
|
157
158
|
name: string;
|
|
158
159
|
vulnerabilityScanIntervalHours: number;
|
|
159
160
|
scanRequestedAt: string | null;
|
|
161
|
+
techScanRequestedAt: string | null;
|
|
160
162
|
} | null>;
|
|
161
163
|
/**
|
|
162
164
|
* Setup automatic vulnerability scanning based on server-configured interval.
|
|
@@ -169,7 +171,7 @@ declare class MonitorClient {
|
|
|
169
171
|
*/
|
|
170
172
|
private runScanAndTrackTime;
|
|
171
173
|
/**
|
|
172
|
-
* Check if the server has requested an on-demand scan.
|
|
174
|
+
* Check if the server has requested an on-demand scan (vulnerability or technology).
|
|
173
175
|
*/
|
|
174
176
|
private checkForScanRequest;
|
|
175
177
|
private enqueue;
|
package/dist/index.d.ts
CHANGED
|
@@ -142,6 +142,7 @@ declare class MonitorClient {
|
|
|
142
142
|
private settingsPollingTimer;
|
|
143
143
|
private lastScanTime;
|
|
144
144
|
private lastKnownScanRequestedAt;
|
|
145
|
+
private lastKnownTechScanRequestedAt;
|
|
145
146
|
constructor(config: MonitorClientConfig);
|
|
146
147
|
captureError(error: Error, context?: ErrorContext): Promise<void>;
|
|
147
148
|
captureMessage(message: string, severity?: Severity, context?: ErrorContext): Promise<void>;
|
|
@@ -151,12 +152,13 @@ declare class MonitorClient {
|
|
|
151
152
|
private stopAuditIntervalTimer;
|
|
152
153
|
/**
|
|
153
154
|
* Fetch project settings from the monitoring server.
|
|
154
|
-
* Returns configuration including vulnerability scan interval and scan request
|
|
155
|
+
* Returns configuration including vulnerability scan interval and scan request timestamps.
|
|
155
156
|
*/
|
|
156
157
|
fetchProjectSettings(): Promise<{
|
|
157
158
|
name: string;
|
|
158
159
|
vulnerabilityScanIntervalHours: number;
|
|
159
160
|
scanRequestedAt: string | null;
|
|
161
|
+
techScanRequestedAt: string | null;
|
|
160
162
|
} | null>;
|
|
161
163
|
/**
|
|
162
164
|
* Setup automatic vulnerability scanning based on server-configured interval.
|
|
@@ -169,7 +171,7 @@ declare class MonitorClient {
|
|
|
169
171
|
*/
|
|
170
172
|
private runScanAndTrackTime;
|
|
171
173
|
/**
|
|
172
|
-
* Check if the server has requested an on-demand scan.
|
|
174
|
+
* Check if the server has requested an on-demand scan (vulnerability or technology).
|
|
173
175
|
*/
|
|
174
176
|
private checkForScanRequest;
|
|
175
177
|
private enqueue;
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ var MonitorClient = class {
|
|
|
46
46
|
this.settingsPollingTimer = null;
|
|
47
47
|
this.lastScanTime = null;
|
|
48
48
|
this.lastKnownScanRequestedAt = null;
|
|
49
|
+
this.lastKnownTechScanRequestedAt = null;
|
|
49
50
|
if (!config.apiKey || config.apiKey.trim().length === 0) {
|
|
50
51
|
throw new Error("[MonitorClient] API key is required");
|
|
51
52
|
}
|
|
@@ -193,7 +194,7 @@ var MonitorClient = class {
|
|
|
193
194
|
}
|
|
194
195
|
/**
|
|
195
196
|
* Fetch project settings from the monitoring server.
|
|
196
|
-
* Returns configuration including vulnerability scan interval and scan request
|
|
197
|
+
* Returns configuration including vulnerability scan interval and scan request timestamps.
|
|
197
198
|
*/
|
|
198
199
|
async fetchProjectSettings() {
|
|
199
200
|
try {
|
|
@@ -229,6 +230,9 @@ var MonitorClient = class {
|
|
|
229
230
|
if (settings.scanRequestedAt) {
|
|
230
231
|
this.lastKnownScanRequestedAt = new Date(settings.scanRequestedAt);
|
|
231
232
|
}
|
|
233
|
+
if (settings.techScanRequestedAt) {
|
|
234
|
+
this.lastKnownTechScanRequestedAt = new Date(settings.techScanRequestedAt);
|
|
235
|
+
}
|
|
232
236
|
const intervalHours = settings.vulnerabilityScanIntervalHours;
|
|
233
237
|
if (intervalHours <= 0) {
|
|
234
238
|
console.log("[MonitorClient] Scheduled vulnerability scanning disabled by server configuration");
|
|
@@ -257,17 +261,27 @@ var MonitorClient = class {
|
|
|
257
261
|
}
|
|
258
262
|
}
|
|
259
263
|
/**
|
|
260
|
-
* Check if the server has requested an on-demand scan.
|
|
264
|
+
* Check if the server has requested an on-demand scan (vulnerability or technology).
|
|
261
265
|
*/
|
|
262
266
|
async checkForScanRequest() {
|
|
263
267
|
try {
|
|
264
268
|
const settings = await this.fetchProjectSettings();
|
|
265
|
-
if (!settings
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
if (!settings) return;
|
|
270
|
+
if (settings.scanRequestedAt) {
|
|
271
|
+
const scanRequestedAt = new Date(settings.scanRequestedAt);
|
|
272
|
+
if (!this.lastKnownScanRequestedAt || scanRequestedAt > this.lastKnownScanRequestedAt) {
|
|
273
|
+
console.log("[MonitorClient] On-demand vulnerability scan requested by server");
|
|
274
|
+
this.lastKnownScanRequestedAt = scanRequestedAt;
|
|
275
|
+
await this.runScanAndTrackTime();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (settings.techScanRequestedAt) {
|
|
279
|
+
const techScanRequestedAt = new Date(settings.techScanRequestedAt);
|
|
280
|
+
if (!this.lastKnownTechScanRequestedAt || techScanRequestedAt > this.lastKnownTechScanRequestedAt) {
|
|
281
|
+
console.log("[MonitorClient] On-demand technology scan requested by server");
|
|
282
|
+
this.lastKnownTechScanRequestedAt = techScanRequestedAt;
|
|
283
|
+
await this.syncDependencies();
|
|
284
|
+
}
|
|
271
285
|
}
|
|
272
286
|
} catch (err) {
|
|
273
287
|
console.error("[MonitorClient] Failed to check for scan request:", err instanceof Error ? err.message : String(err));
|
|
@@ -286,12 +300,12 @@ var MonitorClient = class {
|
|
|
286
300
|
/**
|
|
287
301
|
* Fetch with timeout to prevent hanging requests
|
|
288
302
|
*/
|
|
289
|
-
async fetchWithTimeout(url,
|
|
303
|
+
async fetchWithTimeout(url, options, timeoutMs = this.requestTimeoutMs) {
|
|
290
304
|
const controller = new AbortController();
|
|
291
305
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
292
306
|
try {
|
|
293
307
|
const response = await fetch(url, {
|
|
294
|
-
...
|
|
308
|
+
...options,
|
|
295
309
|
signal: controller.signal
|
|
296
310
|
});
|
|
297
311
|
return response;
|
|
@@ -374,13 +388,13 @@ var MonitorClient = class {
|
|
|
374
388
|
try {
|
|
375
389
|
const fsModule = await import("fs");
|
|
376
390
|
const pathModule = await import("path");
|
|
377
|
-
const
|
|
378
|
-
const
|
|
391
|
+
const fs = fsModule.default || fsModule;
|
|
392
|
+
const path = pathModule.default || pathModule;
|
|
379
393
|
const baseDir = process.cwd();
|
|
380
|
-
const resolvedPath =
|
|
381
|
-
const normalizedPath =
|
|
382
|
-
const normalizedBase =
|
|
383
|
-
if (!
|
|
394
|
+
const resolvedPath = path.isAbsolute(packagePath) ? packagePath : path.join(baseDir, packagePath);
|
|
395
|
+
const normalizedPath = path.normalize(resolvedPath);
|
|
396
|
+
const normalizedBase = path.normalize(baseDir);
|
|
397
|
+
if (!path.isAbsolute(packagePath)) {
|
|
384
398
|
if (!normalizedPath.startsWith(normalizedBase)) {
|
|
385
399
|
console.warn("[MonitorClient] Path traversal attempt blocked:", packagePath);
|
|
386
400
|
return [];
|
|
@@ -394,10 +408,10 @@ var MonitorClient = class {
|
|
|
394
408
|
console.warn("[MonitorClient] Path must point to package.json");
|
|
395
409
|
return [];
|
|
396
410
|
}
|
|
397
|
-
if (!
|
|
411
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
398
412
|
return [];
|
|
399
413
|
}
|
|
400
|
-
const packageJson = JSON.parse(
|
|
414
|
+
const packageJson = JSON.parse(fs.readFileSync(normalizedPath, "utf-8"));
|
|
401
415
|
const technologies = [];
|
|
402
416
|
const deps = {
|
|
403
417
|
...packageJson.dependencies,
|
|
@@ -431,7 +445,7 @@ var MonitorClient = class {
|
|
|
431
445
|
async sendTechnologies(technologies) {
|
|
432
446
|
await this.sendTechnologiesWithEnvironment(technologies, this.environment);
|
|
433
447
|
}
|
|
434
|
-
async sendTechnologiesWithEnvironment(technologies,
|
|
448
|
+
async sendTechnologiesWithEnvironment(technologies, environment) {
|
|
435
449
|
const response = await this.fetchWithTimeout(`${this.endpoint}/api/v1/technologies/sync`, {
|
|
436
450
|
method: "POST",
|
|
437
451
|
headers: {
|
|
@@ -439,7 +453,7 @@ var MonitorClient = class {
|
|
|
439
453
|
Authorization: `Bearer ${this.apiKey}`
|
|
440
454
|
},
|
|
441
455
|
body: JSON.stringify({
|
|
442
|
-
environment
|
|
456
|
+
environment,
|
|
443
457
|
technologies
|
|
444
458
|
})
|
|
445
459
|
});
|
|
@@ -476,74 +490,74 @@ var MonitorClient = class {
|
|
|
476
490
|
/**
|
|
477
491
|
* Capture a login failure event (convenience method)
|
|
478
492
|
*/
|
|
479
|
-
async captureLoginFailure(
|
|
493
|
+
async captureLoginFailure(options) {
|
|
480
494
|
return this.captureSecurityEvent({
|
|
481
|
-
eventType: `login_failed_${
|
|
495
|
+
eventType: `login_failed_${options.authMethod || "other"}`,
|
|
482
496
|
category: "AUTHENTICATION",
|
|
483
497
|
severity: "MEDIUM",
|
|
484
|
-
ip:
|
|
485
|
-
identifier:
|
|
486
|
-
endpoint:
|
|
487
|
-
userAgent:
|
|
488
|
-
metadata: { reason:
|
|
498
|
+
ip: options.ip,
|
|
499
|
+
identifier: options.identifier,
|
|
500
|
+
endpoint: options.endpoint,
|
|
501
|
+
userAgent: options.userAgent,
|
|
502
|
+
metadata: { reason: options.reason, authMethod: options.authMethod }
|
|
489
503
|
});
|
|
490
504
|
}
|
|
491
505
|
/**
|
|
492
506
|
* Capture a successful login event
|
|
493
507
|
*/
|
|
494
|
-
async captureLoginSuccess(
|
|
508
|
+
async captureLoginSuccess(options) {
|
|
495
509
|
await this.captureSecurityEvent({
|
|
496
|
-
eventType: `login_success_${
|
|
510
|
+
eventType: `login_success_${options.authMethod || "other"}`,
|
|
497
511
|
category: "AUTHENTICATION",
|
|
498
512
|
severity: "LOW",
|
|
499
|
-
ip:
|
|
500
|
-
identifier:
|
|
501
|
-
endpoint:
|
|
502
|
-
userAgent:
|
|
503
|
-
metadata: { authMethod:
|
|
513
|
+
ip: options.ip,
|
|
514
|
+
identifier: options.identifier,
|
|
515
|
+
endpoint: options.endpoint,
|
|
516
|
+
userAgent: options.userAgent,
|
|
517
|
+
metadata: { authMethod: options.authMethod }
|
|
504
518
|
});
|
|
505
519
|
}
|
|
506
520
|
/**
|
|
507
521
|
* Capture a rate limit event
|
|
508
522
|
*/
|
|
509
|
-
async captureRateLimit(
|
|
523
|
+
async captureRateLimit(options) {
|
|
510
524
|
await this.captureSecurityEvent({
|
|
511
525
|
eventType: "rate_limit_exceeded",
|
|
512
526
|
category: "RATE_LIMIT",
|
|
513
527
|
severity: "MEDIUM",
|
|
514
|
-
ip:
|
|
515
|
-
identifier:
|
|
516
|
-
endpoint:
|
|
517
|
-
userAgent:
|
|
518
|
-
metadata: { limit:
|
|
528
|
+
ip: options.ip,
|
|
529
|
+
identifier: options.identifier,
|
|
530
|
+
endpoint: options.endpoint,
|
|
531
|
+
userAgent: options.userAgent,
|
|
532
|
+
metadata: { limit: options.limit, window: options.window }
|
|
519
533
|
});
|
|
520
534
|
}
|
|
521
535
|
/**
|
|
522
536
|
* Capture an authorization failure (user tried to access unauthorized resource)
|
|
523
537
|
*/
|
|
524
|
-
async captureAuthorizationFailure(
|
|
538
|
+
async captureAuthorizationFailure(options) {
|
|
525
539
|
await this.captureSecurityEvent({
|
|
526
540
|
eventType: "authorization_denied",
|
|
527
541
|
category: "AUTHORIZATION",
|
|
528
542
|
severity: "MEDIUM",
|
|
529
|
-
ip:
|
|
530
|
-
identifier:
|
|
531
|
-
endpoint:
|
|
532
|
-
userAgent:
|
|
533
|
-
metadata: { resource:
|
|
543
|
+
ip: options.ip,
|
|
544
|
+
identifier: options.identifier,
|
|
545
|
+
endpoint: options.endpoint,
|
|
546
|
+
userAgent: options.userAgent,
|
|
547
|
+
metadata: { resource: options.resource, action: options.action }
|
|
534
548
|
});
|
|
535
549
|
}
|
|
536
550
|
/**
|
|
537
551
|
* Check if an IP or identifier has triggered brute force detection
|
|
538
552
|
*/
|
|
539
|
-
async checkBruteForce(
|
|
553
|
+
async checkBruteForce(options) {
|
|
540
554
|
const response = await this.fetchWithTimeout(`${this.endpoint}/api/v1/security/detect/brute-force`, {
|
|
541
555
|
method: "POST",
|
|
542
556
|
headers: {
|
|
543
557
|
"Content-Type": "application/json",
|
|
544
558
|
Authorization: `Bearer ${this.apiKey}`
|
|
545
559
|
},
|
|
546
|
-
body: JSON.stringify(
|
|
560
|
+
body: JSON.stringify(options)
|
|
547
561
|
});
|
|
548
562
|
if (!response.ok) {
|
|
549
563
|
const errorText = await response.text().catch(() => "");
|
|
@@ -569,10 +583,12 @@ var MonitorClient = class {
|
|
|
569
583
|
let path;
|
|
570
584
|
let fs;
|
|
571
585
|
try {
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
586
|
+
const childProcess = await import("child_process");
|
|
587
|
+
const pathModule = await import("path");
|
|
588
|
+
const fsModule = await import("fs");
|
|
589
|
+
execSync = childProcess.execSync;
|
|
590
|
+
path = pathModule;
|
|
591
|
+
fs = fsModule;
|
|
576
592
|
} catch {
|
|
577
593
|
console.warn("[MonitorClient] auditDependencies requires Node.js (not available in bundled/browser environments)");
|
|
578
594
|
return null;
|
package/dist/index.mjs
CHANGED
|
@@ -10,6 +10,7 @@ var MonitorClient = class {
|
|
|
10
10
|
this.settingsPollingTimer = null;
|
|
11
11
|
this.lastScanTime = null;
|
|
12
12
|
this.lastKnownScanRequestedAt = null;
|
|
13
|
+
this.lastKnownTechScanRequestedAt = null;
|
|
13
14
|
if (!config.apiKey || config.apiKey.trim().length === 0) {
|
|
14
15
|
throw new Error("[MonitorClient] API key is required");
|
|
15
16
|
}
|
|
@@ -157,7 +158,7 @@ var MonitorClient = class {
|
|
|
157
158
|
}
|
|
158
159
|
/**
|
|
159
160
|
* Fetch project settings from the monitoring server.
|
|
160
|
-
* Returns configuration including vulnerability scan interval and scan request
|
|
161
|
+
* Returns configuration including vulnerability scan interval and scan request timestamps.
|
|
161
162
|
*/
|
|
162
163
|
async fetchProjectSettings() {
|
|
163
164
|
try {
|
|
@@ -193,6 +194,9 @@ var MonitorClient = class {
|
|
|
193
194
|
if (settings.scanRequestedAt) {
|
|
194
195
|
this.lastKnownScanRequestedAt = new Date(settings.scanRequestedAt);
|
|
195
196
|
}
|
|
197
|
+
if (settings.techScanRequestedAt) {
|
|
198
|
+
this.lastKnownTechScanRequestedAt = new Date(settings.techScanRequestedAt);
|
|
199
|
+
}
|
|
196
200
|
const intervalHours = settings.vulnerabilityScanIntervalHours;
|
|
197
201
|
if (intervalHours <= 0) {
|
|
198
202
|
console.log("[MonitorClient] Scheduled vulnerability scanning disabled by server configuration");
|
|
@@ -221,17 +225,27 @@ var MonitorClient = class {
|
|
|
221
225
|
}
|
|
222
226
|
}
|
|
223
227
|
/**
|
|
224
|
-
* Check if the server has requested an on-demand scan.
|
|
228
|
+
* Check if the server has requested an on-demand scan (vulnerability or technology).
|
|
225
229
|
*/
|
|
226
230
|
async checkForScanRequest() {
|
|
227
231
|
try {
|
|
228
232
|
const settings = await this.fetchProjectSettings();
|
|
229
|
-
if (!settings
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
if (!settings) return;
|
|
234
|
+
if (settings.scanRequestedAt) {
|
|
235
|
+
const scanRequestedAt = new Date(settings.scanRequestedAt);
|
|
236
|
+
if (!this.lastKnownScanRequestedAt || scanRequestedAt > this.lastKnownScanRequestedAt) {
|
|
237
|
+
console.log("[MonitorClient] On-demand vulnerability scan requested by server");
|
|
238
|
+
this.lastKnownScanRequestedAt = scanRequestedAt;
|
|
239
|
+
await this.runScanAndTrackTime();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (settings.techScanRequestedAt) {
|
|
243
|
+
const techScanRequestedAt = new Date(settings.techScanRequestedAt);
|
|
244
|
+
if (!this.lastKnownTechScanRequestedAt || techScanRequestedAt > this.lastKnownTechScanRequestedAt) {
|
|
245
|
+
console.log("[MonitorClient] On-demand technology scan requested by server");
|
|
246
|
+
this.lastKnownTechScanRequestedAt = techScanRequestedAt;
|
|
247
|
+
await this.syncDependencies();
|
|
248
|
+
}
|
|
235
249
|
}
|
|
236
250
|
} catch (err) {
|
|
237
251
|
console.error("[MonitorClient] Failed to check for scan request:", err instanceof Error ? err.message : String(err));
|
|
@@ -250,12 +264,12 @@ var MonitorClient = class {
|
|
|
250
264
|
/**
|
|
251
265
|
* Fetch with timeout to prevent hanging requests
|
|
252
266
|
*/
|
|
253
|
-
async fetchWithTimeout(url,
|
|
267
|
+
async fetchWithTimeout(url, options, timeoutMs = this.requestTimeoutMs) {
|
|
254
268
|
const controller = new AbortController();
|
|
255
269
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
256
270
|
try {
|
|
257
271
|
const response = await fetch(url, {
|
|
258
|
-
...
|
|
272
|
+
...options,
|
|
259
273
|
signal: controller.signal
|
|
260
274
|
});
|
|
261
275
|
return response;
|
|
@@ -338,13 +352,13 @@ var MonitorClient = class {
|
|
|
338
352
|
try {
|
|
339
353
|
const fsModule = await import("fs");
|
|
340
354
|
const pathModule = await import("path");
|
|
341
|
-
const
|
|
342
|
-
const
|
|
355
|
+
const fs = fsModule.default || fsModule;
|
|
356
|
+
const path = pathModule.default || pathModule;
|
|
343
357
|
const baseDir = process.cwd();
|
|
344
|
-
const resolvedPath =
|
|
345
|
-
const normalizedPath =
|
|
346
|
-
const normalizedBase =
|
|
347
|
-
if (!
|
|
358
|
+
const resolvedPath = path.isAbsolute(packagePath) ? packagePath : path.join(baseDir, packagePath);
|
|
359
|
+
const normalizedPath = path.normalize(resolvedPath);
|
|
360
|
+
const normalizedBase = path.normalize(baseDir);
|
|
361
|
+
if (!path.isAbsolute(packagePath)) {
|
|
348
362
|
if (!normalizedPath.startsWith(normalizedBase)) {
|
|
349
363
|
console.warn("[MonitorClient] Path traversal attempt blocked:", packagePath);
|
|
350
364
|
return [];
|
|
@@ -358,10 +372,10 @@ var MonitorClient = class {
|
|
|
358
372
|
console.warn("[MonitorClient] Path must point to package.json");
|
|
359
373
|
return [];
|
|
360
374
|
}
|
|
361
|
-
if (!
|
|
375
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
362
376
|
return [];
|
|
363
377
|
}
|
|
364
|
-
const packageJson = JSON.parse(
|
|
378
|
+
const packageJson = JSON.parse(fs.readFileSync(normalizedPath, "utf-8"));
|
|
365
379
|
const technologies = [];
|
|
366
380
|
const deps = {
|
|
367
381
|
...packageJson.dependencies,
|
|
@@ -395,7 +409,7 @@ var MonitorClient = class {
|
|
|
395
409
|
async sendTechnologies(technologies) {
|
|
396
410
|
await this.sendTechnologiesWithEnvironment(technologies, this.environment);
|
|
397
411
|
}
|
|
398
|
-
async sendTechnologiesWithEnvironment(technologies,
|
|
412
|
+
async sendTechnologiesWithEnvironment(technologies, environment) {
|
|
399
413
|
const response = await this.fetchWithTimeout(`${this.endpoint}/api/v1/technologies/sync`, {
|
|
400
414
|
method: "POST",
|
|
401
415
|
headers: {
|
|
@@ -403,7 +417,7 @@ var MonitorClient = class {
|
|
|
403
417
|
Authorization: `Bearer ${this.apiKey}`
|
|
404
418
|
},
|
|
405
419
|
body: JSON.stringify({
|
|
406
|
-
environment
|
|
420
|
+
environment,
|
|
407
421
|
technologies
|
|
408
422
|
})
|
|
409
423
|
});
|
|
@@ -440,74 +454,74 @@ var MonitorClient = class {
|
|
|
440
454
|
/**
|
|
441
455
|
* Capture a login failure event (convenience method)
|
|
442
456
|
*/
|
|
443
|
-
async captureLoginFailure(
|
|
457
|
+
async captureLoginFailure(options) {
|
|
444
458
|
return this.captureSecurityEvent({
|
|
445
|
-
eventType: `login_failed_${
|
|
459
|
+
eventType: `login_failed_${options.authMethod || "other"}`,
|
|
446
460
|
category: "AUTHENTICATION",
|
|
447
461
|
severity: "MEDIUM",
|
|
448
|
-
ip:
|
|
449
|
-
identifier:
|
|
450
|
-
endpoint:
|
|
451
|
-
userAgent:
|
|
452
|
-
metadata: { reason:
|
|
462
|
+
ip: options.ip,
|
|
463
|
+
identifier: options.identifier,
|
|
464
|
+
endpoint: options.endpoint,
|
|
465
|
+
userAgent: options.userAgent,
|
|
466
|
+
metadata: { reason: options.reason, authMethod: options.authMethod }
|
|
453
467
|
});
|
|
454
468
|
}
|
|
455
469
|
/**
|
|
456
470
|
* Capture a successful login event
|
|
457
471
|
*/
|
|
458
|
-
async captureLoginSuccess(
|
|
472
|
+
async captureLoginSuccess(options) {
|
|
459
473
|
await this.captureSecurityEvent({
|
|
460
|
-
eventType: `login_success_${
|
|
474
|
+
eventType: `login_success_${options.authMethod || "other"}`,
|
|
461
475
|
category: "AUTHENTICATION",
|
|
462
476
|
severity: "LOW",
|
|
463
|
-
ip:
|
|
464
|
-
identifier:
|
|
465
|
-
endpoint:
|
|
466
|
-
userAgent:
|
|
467
|
-
metadata: { authMethod:
|
|
477
|
+
ip: options.ip,
|
|
478
|
+
identifier: options.identifier,
|
|
479
|
+
endpoint: options.endpoint,
|
|
480
|
+
userAgent: options.userAgent,
|
|
481
|
+
metadata: { authMethod: options.authMethod }
|
|
468
482
|
});
|
|
469
483
|
}
|
|
470
484
|
/**
|
|
471
485
|
* Capture a rate limit event
|
|
472
486
|
*/
|
|
473
|
-
async captureRateLimit(
|
|
487
|
+
async captureRateLimit(options) {
|
|
474
488
|
await this.captureSecurityEvent({
|
|
475
489
|
eventType: "rate_limit_exceeded",
|
|
476
490
|
category: "RATE_LIMIT",
|
|
477
491
|
severity: "MEDIUM",
|
|
478
|
-
ip:
|
|
479
|
-
identifier:
|
|
480
|
-
endpoint:
|
|
481
|
-
userAgent:
|
|
482
|
-
metadata: { limit:
|
|
492
|
+
ip: options.ip,
|
|
493
|
+
identifier: options.identifier,
|
|
494
|
+
endpoint: options.endpoint,
|
|
495
|
+
userAgent: options.userAgent,
|
|
496
|
+
metadata: { limit: options.limit, window: options.window }
|
|
483
497
|
});
|
|
484
498
|
}
|
|
485
499
|
/**
|
|
486
500
|
* Capture an authorization failure (user tried to access unauthorized resource)
|
|
487
501
|
*/
|
|
488
|
-
async captureAuthorizationFailure(
|
|
502
|
+
async captureAuthorizationFailure(options) {
|
|
489
503
|
await this.captureSecurityEvent({
|
|
490
504
|
eventType: "authorization_denied",
|
|
491
505
|
category: "AUTHORIZATION",
|
|
492
506
|
severity: "MEDIUM",
|
|
493
|
-
ip:
|
|
494
|
-
identifier:
|
|
495
|
-
endpoint:
|
|
496
|
-
userAgent:
|
|
497
|
-
metadata: { resource:
|
|
507
|
+
ip: options.ip,
|
|
508
|
+
identifier: options.identifier,
|
|
509
|
+
endpoint: options.endpoint,
|
|
510
|
+
userAgent: options.userAgent,
|
|
511
|
+
metadata: { resource: options.resource, action: options.action }
|
|
498
512
|
});
|
|
499
513
|
}
|
|
500
514
|
/**
|
|
501
515
|
* Check if an IP or identifier has triggered brute force detection
|
|
502
516
|
*/
|
|
503
|
-
async checkBruteForce(
|
|
517
|
+
async checkBruteForce(options) {
|
|
504
518
|
const response = await this.fetchWithTimeout(`${this.endpoint}/api/v1/security/detect/brute-force`, {
|
|
505
519
|
method: "POST",
|
|
506
520
|
headers: {
|
|
507
521
|
"Content-Type": "application/json",
|
|
508
522
|
Authorization: `Bearer ${this.apiKey}`
|
|
509
523
|
},
|
|
510
|
-
body: JSON.stringify(
|
|
524
|
+
body: JSON.stringify(options)
|
|
511
525
|
});
|
|
512
526
|
if (!response.ok) {
|
|
513
527
|
const errorText = await response.text().catch(() => "");
|
|
@@ -533,10 +547,12 @@ var MonitorClient = class {
|
|
|
533
547
|
let path;
|
|
534
548
|
let fs;
|
|
535
549
|
try {
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
550
|
+
const childProcess = await import("child_process");
|
|
551
|
+
const pathModule = await import("path");
|
|
552
|
+
const fsModule = await import("fs");
|
|
553
|
+
execSync = childProcess.execSync;
|
|
554
|
+
path = pathModule;
|
|
555
|
+
fs = fsModule;
|
|
540
556
|
} catch {
|
|
541
557
|
console.warn("[MonitorClient] auditDependencies requires Node.js (not available in bundled/browser environments)");
|
|
542
558
|
return null;
|
package/package.json
CHANGED