safe-link-checker 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,497 @@
1
+ /**
2
+ * SafeLinkChecker
3
+ * Copyright (c) 2026
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ type RiskLevel = 'SAFE' | 'SUSPICIOUS' | 'DANGEROUS';
9
+ type HttpsStatus = 'HTTPS' | 'HTTP_ONLY' | 'CERT_ERROR' | 'TIMEOUT' | 'UNREACHABLE' | 'SKIPPED';
10
+ type RedirectAnomalyKind = 'LOOP' | 'PROTOCOL_DOWNGRADE' | 'MAX_REDIRECTS_EXCEEDED';
11
+ type RiskCategory = 'domain' | 'certificate' | 'redirect' | 'content' | 'network' | 'provider' | 'browser' | 'email' | 'qr' | 'download' | 'behavior' | 'ai' | 'other';
12
+ type RiskSeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';
13
+ type DecisionAction = 'allow' | 'warn' | 'review' | 'block';
14
+ interface VerifyOptions {
15
+ maxRedirects?: number;
16
+ timeout?: number;
17
+ customShorteners?: string[];
18
+ bypassCache?: boolean;
19
+ removeTrackingParams?: boolean;
20
+ checkHttps?: boolean;
21
+ signal?: AbortSignal;
22
+ policy?: string;
23
+ }
24
+ interface CheckResult {
25
+ name: string;
26
+ safe: boolean;
27
+ scoreImpact: number;
28
+ message: string;
29
+ weight?: number;
30
+ fatal?: boolean;
31
+ detector?: string;
32
+ category?: RiskCategory;
33
+ severity?: RiskSeverity;
34
+ confidence?: number;
35
+ scoreContribution?: number;
36
+ title?: string;
37
+ description?: string;
38
+ recommendation?: string;
39
+ references?: string[];
40
+ executionTime?: number;
41
+ timestamp?: number;
42
+ metadata?: Record<string, unknown>;
43
+ }
44
+ interface Provider {
45
+ name: string;
46
+ check(url: string, options?: VerifyOptions): Promise<CheckResult | null>;
47
+ }
48
+ interface RedirectHop {
49
+ url: string;
50
+ statusCode: number;
51
+ }
52
+ interface RedirectTrace$1 {
53
+ chain: string[];
54
+ finalUrl: string;
55
+ redirectCount: number;
56
+ anomalies: RedirectAnomalyKind[];
57
+ }
58
+ interface ExecutionTimeline {
59
+ phase: string;
60
+ startTime: number;
61
+ durationMs: number;
62
+ status: 'success' | 'error' | 'skipped';
63
+ }
64
+ interface RichMetadata {
65
+ favicon?: string;
66
+ title?: string;
67
+ description?: string;
68
+ openGraph?: Record<string, string>;
69
+ twitterCards?: Record<string, string>;
70
+ canonicalUrl?: string;
71
+ detectedBrand?: string;
72
+ detectedLanguage?: string;
73
+ contentType?: string;
74
+ server?: string;
75
+ country?: string;
76
+ hostingProvider?: string;
77
+ asn?: string;
78
+ }
79
+ interface ExecutionStats {
80
+ totalTimeMs: number;
81
+ startTime: number;
82
+ endTime: number;
83
+ }
84
+ interface VerificationResult {
85
+ url: string;
86
+ normalizedUrl: string;
87
+ safe: boolean;
88
+ score: number;
89
+ confidence: number;
90
+ riskLevel: RiskLevel;
91
+ reasons: string[];
92
+ recommendations: string[];
93
+ redirectChain: string[];
94
+ redirectTrace: RedirectTrace$1;
95
+ checks: CheckResult[];
96
+ fromCache: boolean;
97
+ decision?: DecisionAction;
98
+ trustScore?: number;
99
+ summary?: string;
100
+ action?: string;
101
+ policy?: string;
102
+ timeline?: ExecutionTimeline[];
103
+ evidence?: CheckResult[];
104
+ providerResults?: CheckResult[];
105
+ categories?: Record<string, number>;
106
+ execution?: ExecutionStats;
107
+ metadata?: RichMetadata | Record<string, unknown>;
108
+ }
109
+
110
+ /**
111
+ * SafeLinkChecker
112
+ * Copyright (c) 2026
113
+ *
114
+ * This source code is licensed under the MIT license found in the
115
+ * LICENSE file in the root directory of this source tree.
116
+ */
117
+
118
+ declare function verifyLink(url: string, options?: VerifyOptions): Promise<VerificationResult>;
119
+
120
+ /**
121
+ * SafeLinkChecker
122
+ * Copyright (c) 2026
123
+ *
124
+ * This source code is licensed under the MIT license found in the
125
+ * LICENSE file in the root directory of this source tree.
126
+ */
127
+ interface MetadataResult {
128
+ title?: string;
129
+ description?: string;
130
+ image?: string;
131
+ favicon?: string;
132
+ url?: string;
133
+ }
134
+
135
+ /**
136
+ * SafeLinkChecker
137
+ * Copyright (c) 2026
138
+ *
139
+ * This source code is licensed under the MIT license found in the
140
+ * LICENSE file in the root directory of this source tree.
141
+ */
142
+ type EventCallback = (...args: unknown[]) => void;
143
+ declare class EventEmitter {
144
+ private listeners;
145
+ on(event: string, callback: EventCallback): void;
146
+ off(event: string, callback: EventCallback): void;
147
+ emit(event: string, arg1?: unknown, arg2?: unknown): void;
148
+ }
149
+
150
+ /**
151
+ * SafeLinkChecker
152
+ * Copyright (c) 2026
153
+ *
154
+ * This source code is licensed under the MIT license found in the
155
+ * LICENSE file in the root directory of this source tree.
156
+ */
157
+
158
+ type PluginType = 'network' | 'content' | 'heuristic' | 'provider';
159
+ interface RedirectTrace {
160
+ finalUrl: string;
161
+ redirectCount: number;
162
+ chain: string[];
163
+ anomalies: RedirectAnomalyKind[];
164
+ }
165
+ interface PluginState {
166
+ finalUrl?: string;
167
+ isShortener?: boolean;
168
+ redirectTrace?: RedirectTrace;
169
+ [key: string]: unknown;
170
+ }
171
+ interface PluginContext {
172
+ url: string;
173
+ normalizedUrl: string;
174
+ options: VerifyOptions;
175
+ state: PluginState;
176
+ }
177
+ interface VerificationPlugin {
178
+ id: string;
179
+ name: string;
180
+ version: string;
181
+ description: string;
182
+ author: string;
183
+ type: PluginType;
184
+ capabilities: string[];
185
+ priority: number;
186
+ weight?: number;
187
+ /**
188
+ * Initialization hook (e.g. connecting to DB, setting up local models)
189
+ */
190
+ initialize?(): Promise<void>;
191
+ /**
192
+ * Main execution hook.
193
+ * Returns a CheckResult or null if the plugin decides to skip.
194
+ */
195
+ execute(ctx: PluginContext): Promise<CheckResult | null>;
196
+ /**
197
+ * Optional teardown hook
198
+ */
199
+ dispose?(): Promise<void>;
200
+ /**
201
+ * Optional health check hook
202
+ */
203
+ health?(): Promise<boolean>;
204
+ }
205
+ declare class PluginManager {
206
+ private plugins;
207
+ register(plugin: VerificationPlugin): void;
208
+ initializeAll(): Promise<void>;
209
+ disposeAll(): Promise<void>;
210
+ getPluginsByType(type: PluginType): VerificationPlugin[];
211
+ getAll(): VerificationPlugin[];
212
+ }
213
+
214
+ /**
215
+ * SafeLinkChecker
216
+ * Copyright (c) 2026
217
+ *
218
+ * This source code is licensed under the MIT license found in the
219
+ * LICENSE file in the root directory of this source tree.
220
+ */
221
+
222
+ interface ConsensusConfig {
223
+ baseScore: number;
224
+ riskThresholds: {
225
+ suspicious: number;
226
+ dangerous: number;
227
+ };
228
+ }
229
+ interface ConsensusResult {
230
+ score: number;
231
+ trustScore: number;
232
+ confidence: number;
233
+ riskLevel: RiskLevel;
234
+ reasons: string[];
235
+ safe: boolean;
236
+ summary: string;
237
+ }
238
+ declare class ConsensusEngine {
239
+ private config;
240
+ constructor(config?: Partial<ConsensusConfig>);
241
+ evaluate(results: (CheckResult | null)[]): ConsensusResult;
242
+ }
243
+
244
+ /**
245
+ * SafeLinkChecker
246
+ * Copyright (c) 2026
247
+ *
248
+ * This source code is licensed under the MIT license found in the
249
+ * LICENSE file in the root directory of this source tree.
250
+ */
251
+
252
+ interface PolicyContext {
253
+ riskLevel: RiskLevel;
254
+ score: number;
255
+ confidence: number;
256
+ }
257
+ interface PolicyResult {
258
+ decision: DecisionAction;
259
+ action: string;
260
+ }
261
+ type PolicyDefinition = (ctx: PolicyContext) => PolicyResult;
262
+ declare class PolicyEngine {
263
+ private policies;
264
+ constructor();
265
+ private registerBuiltIns;
266
+ register(name: string, policy: PolicyDefinition): void;
267
+ evaluate(policyName: string | undefined, ctx: PolicyContext): PolicyResult;
268
+ }
269
+
270
+ /**
271
+ * SafeLinkChecker
272
+ * Copyright (c) 2026
273
+ *
274
+ * This source code is licensed under the MIT license found in the
275
+ * LICENSE file in the root directory of this source tree.
276
+ */
277
+
278
+ interface CheckerOptions extends VerifyOptions {
279
+ mode?: 'local' | 'cloud';
280
+ apiKey?: string;
281
+ endpoint?: string;
282
+ cache?: boolean | {
283
+ get(url: string): VerificationResult | null;
284
+ set(url: string, result: VerificationResult): void;
285
+ };
286
+ providers?: (Provider | 'openphish' | 'urlhaus')[];
287
+ onStart?: (url: string) => void;
288
+ onComplete?: (result: VerificationResult) => void;
289
+ onError?: (error: Error, url: string) => void;
290
+ }
291
+ declare class SafeLinkError extends Error {
292
+ constructor(message: string);
293
+ }
294
+ declare class TimeoutError extends SafeLinkError {
295
+ constructor(message: string);
296
+ }
297
+ /**
298
+ * The main orchestrator for validating URLs.
299
+ * Allows configuration of caching, timeouts, concurrent provider plugins, and batch processing.
300
+ */
301
+ declare class SafeLinkChecker extends EventEmitter {
302
+ private cache;
303
+ private metadataCache;
304
+ private options;
305
+ pluginManager: PluginManager;
306
+ consensusEngine: ConsensusEngine;
307
+ policyEngine: PolicyEngine;
308
+ constructor(options?: CheckerOptions);
309
+ /**
310
+ * Adds a legacy Provider or a new VerificationPlugin to the checker.
311
+ */
312
+ use(plugin: Provider | VerificationPlugin): this;
313
+ getMetadata(url: string): Promise<MetadataResult | null>;
314
+ /**
315
+ * Verifies a single URL through the core engine and any registered providers.
316
+ * Caches results if configured.
317
+ *
318
+ * @param url The URL to check.
319
+ * @param runtimeOptions Options overriding the global checker options for this specific call.
320
+ * @returns A detailed VerificationResult including the final risk score.
321
+ */
322
+ verify(url: string, runtimeOptions?: VerifyOptions): Promise<VerificationResult>;
323
+ private verifyCloud;
324
+ private verifyLocal;
325
+ /**
326
+ * Concurrently verifies multiple URLs with a bounded concurrency limit.
327
+ * Results are returned in the exact same order as the input array.
328
+ *
329
+ * @param urls Array of URLs to verify.
330
+ * @param runtimeOptions Options overriding the global checker options.
331
+ * @param concurrency The maximum number of concurrent verifications (defaults to 5).
332
+ * @returns Array of VerificationResult corresponding to the input URLs.
333
+ */
334
+ verifyLinks(urls: string[], runtimeOptions?: VerifyOptions, concurrency?: number): Promise<VerificationResult[]>;
335
+ }
336
+
337
+ /**
338
+ * SafeLinkChecker
339
+ * Copyright (c) 2026
340
+ *
341
+ * This source code is licensed under the MIT license found in the
342
+ * LICENSE file in the root directory of this source tree.
343
+ */
344
+ declare function normalizeLink(url: string, options?: {
345
+ removeTrackingParams?: boolean;
346
+ }): string;
347
+
348
+ /**
349
+ * SafeLinkChecker
350
+ * Copyright (c) 2026
351
+ *
352
+ * This source code is licensed under the MIT license found in the
353
+ * LICENSE file in the root directory of this source tree.
354
+ */
355
+ interface CacheOptions {
356
+ maxSize?: number;
357
+ ttlMs?: number;
358
+ }
359
+ declare class LRUCache<T> {
360
+ private cache;
361
+ private maxSize;
362
+ private ttlMs;
363
+ constructor(options?: CacheOptions);
364
+ get(url: string): T | null;
365
+ set(url: string, result: T): void;
366
+ clear(): void;
367
+ get size(): number;
368
+ }
369
+
370
+ /**
371
+ * SafeLinkChecker
372
+ * Copyright (c) 2026
373
+ *
374
+ * This source code is licensed under the MIT license found in the
375
+ * LICENSE file in the root directory of this source tree.
376
+ */
377
+
378
+ declare const defaultCache: LRUCache<VerificationResult>;
379
+
380
+ /**
381
+ * SafeLinkChecker
382
+ * Copyright (c) 2026
383
+ *
384
+ * This source code is licensed under the MIT license found in the
385
+ * LICENSE file in the root directory of this source tree.
386
+ */
387
+
388
+ declare function validateUrl(urlStr: string): CheckResult;
389
+
390
+ /**
391
+ * SafeLinkChecker
392
+ * Copyright (c) 2026
393
+ *
394
+ * This source code is licensed under the MIT license found in the
395
+ * LICENSE file in the root directory of this source tree.
396
+ */
397
+
398
+ /**
399
+ * Probes the URL for HTTPS availability and certificate validity.
400
+ * Returns a CheckResult that is always fulfilled — never rejects.
401
+ *
402
+ * Score impact guide:
403
+ * HTTPS → 0 (good)
404
+ * HTTP_ONLY → 20 (SUSPICIOUS — no encryption)
405
+ * CERT_ERROR → 40 (DANGEROUS — cert problem, MITM risk)
406
+ * TIMEOUT → 0 (ambiguous; don't penalise for slow servers)
407
+ * UNREACHABLE → 0 (ambiguous; server may be fine — just unreachable from CI)
408
+ * SKIPPED → 0 (opt-out)
409
+ */
410
+ declare function validateHttps(urlStr: string, timeoutMs?: number, signal?: AbortSignal): Promise<CheckResult>;
411
+
412
+ /**
413
+ * SafeLinkChecker
414
+ * Copyright (c) 2026
415
+ *
416
+ * This source code is licensed under the MIT license found in the
417
+ * LICENSE file in the root directory of this source tree.
418
+ */
419
+
420
+ declare function validateIp(urlStr: string): CheckResult;
421
+
422
+ /**
423
+ * SafeLinkChecker
424
+ * Copyright (c) 2026
425
+ *
426
+ * This source code is licensed under the MIT license found in the
427
+ * LICENSE file in the root directory of this source tree.
428
+ */
429
+
430
+ declare function validatePunycode(urlStr: string): CheckResult;
431
+
432
+ /**
433
+ * SafeLinkChecker
434
+ * Copyright (c) 2026
435
+ *
436
+ * This source code is licensed under the MIT license found in the
437
+ * LICENSE file in the root directory of this source tree.
438
+ */
439
+
440
+ declare function validateShortener(urlStr: string, customShorteners?: string[]): CheckResult;
441
+
442
+ /**
443
+ * SafeLinkChecker
444
+ * Copyright (c) 2026
445
+ *
446
+ * This source code is licensed under the MIT license found in the
447
+ * LICENSE file in the root directory of this source tree.
448
+ */
449
+
450
+ declare function validateHeuristics(url: string): CheckResult;
451
+
452
+ /**
453
+ * SafeLinkChecker
454
+ * Copyright (c) 2026
455
+ *
456
+ * This source code is licensed under the MIT license found in the
457
+ * LICENSE file in the root directory of this source tree.
458
+ */
459
+
460
+ declare function traceRedirects(urlStr: string, options?: VerifyOptions): Promise<RedirectTrace$1>;
461
+
462
+ /**
463
+ * SafeLinkChecker
464
+ * Copyright (c) 2026
465
+ *
466
+ * This source code is licensed under the MIT license found in the
467
+ * LICENSE file in the root directory of this source tree.
468
+ */
469
+
470
+ declare class URLHausProvider implements Provider {
471
+ name: string;
472
+ private cache;
473
+ private offlineDataset;
474
+ private datasetLoaded;
475
+ private updateInterval;
476
+ init(): Promise<void>;
477
+ private updateDataset;
478
+ check(url: string, options?: VerifyOptions): Promise<CheckResult | null>;
479
+ private doCheckOnline;
480
+ }
481
+
482
+ /**
483
+ * SafeLinkChecker
484
+ * Copyright (c) 2026
485
+ *
486
+ * This source code is licensed under the MIT license found in the
487
+ * LICENSE file in the root directory of this source tree.
488
+ */
489
+
490
+ declare class OpenPhishProvider implements Provider {
491
+ name: string;
492
+ private cache;
493
+ check(url: string, options?: VerifyOptions): Promise<CheckResult | null>;
494
+ private doCheck;
495
+ }
496
+
497
+ export { type CheckResult, type CheckerOptions, type DecisionAction, type ExecutionStats, type ExecutionTimeline, type HttpsStatus, LRUCache, LRUCache as MemoryCache, type MetadataResult, OpenPhishProvider, type Provider, type RedirectAnomalyKind, type RedirectHop, type RedirectTrace$1 as RedirectTrace, type RichMetadata, type RiskCategory, type RiskLevel, type RiskSeverity, SafeLinkChecker, SafeLinkError, TimeoutError, URLHausProvider, type VerificationResult, type VerifyOptions, defaultCache, normalizeLink, traceRedirects, validateHeuristics, validateHttps, validateIp, validatePunycode, validateShortener, validateUrl, verifyLink };