@tindalabs/shield 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.
Files changed (118) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +357 -0
  3. package/dist/assess.d.ts +16 -0
  4. package/dist/assess.js +220 -0
  5. package/dist/config/default-extensions-config.json +103 -0
  6. package/dist/core/ContentProtector.d.ts +63 -0
  7. package/dist/core/ContentProtector.js +281 -0
  8. package/dist/core/index.d.ts +1 -0
  9. package/dist/core/index.js +2 -0
  10. package/dist/core/mediator/ContentProtectionMediator.d.ts +86 -0
  11. package/dist/core/mediator/ContentProtectionMediator.js +238 -0
  12. package/dist/core/mediator/eventDataTypes.d.ts +112 -0
  13. package/dist/core/mediator/eventDataTypes.js +23 -0
  14. package/dist/core/mediator/handlers/abstractEventHandler.d.ts +41 -0
  15. package/dist/core/mediator/handlers/abstractEventHandler.js +59 -0
  16. package/dist/core/mediator/handlers/devToolsEventHandler.d.ts +9 -0
  17. package/dist/core/mediator/handlers/devToolsEventHandler.js +95 -0
  18. package/dist/core/mediator/handlers/eventHandlerRegistry.d.ts +9 -0
  19. package/dist/core/mediator/handlers/eventHandlerRegistry.js +34 -0
  20. package/dist/core/mediator/handlers/extensionEventHandlers.d.ts +40 -0
  21. package/dist/core/mediator/handlers/extensionEventHandlers.js +140 -0
  22. package/dist/core/mediator/handlers/iFrameEventHandlers.d.ts +27 -0
  23. package/dist/core/mediator/handlers/iFrameEventHandlers.js +93 -0
  24. package/dist/core/mediator/handlers/screenShotEventHandlers.d.ts +34 -0
  25. package/dist/core/mediator/handlers/screenShotEventHandlers.js +111 -0
  26. package/dist/core/mediator/protection-event.d.ts +77 -0
  27. package/dist/core/mediator/protection-event.js +32 -0
  28. package/dist/core/mediator/types.d.ts +105 -0
  29. package/dist/core/mediator/types.js +1 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.js +7 -0
  32. package/dist/otel.d.ts +24 -0
  33. package/dist/otel.js +83 -0
  34. package/dist/policy.d.ts +98 -0
  35. package/dist/policy.js +97 -0
  36. package/dist/strategies/AbstractStrategy.d.ts +124 -0
  37. package/dist/strategies/AbstractStrategy.js +256 -0
  38. package/dist/strategies/ClipboardStrategy.d.ts +67 -0
  39. package/dist/strategies/ClipboardStrategy.js +291 -0
  40. package/dist/strategies/ContextMenuStrategy.d.ts +60 -0
  41. package/dist/strategies/ContextMenuStrategy.js +454 -0
  42. package/dist/strategies/DevToolsStrategy.d.ts +55 -0
  43. package/dist/strategies/DevToolsStrategy.js +314 -0
  44. package/dist/strategies/ExtensionStrategy.d.ts +66 -0
  45. package/dist/strategies/ExtensionStrategy.js +486 -0
  46. package/dist/strategies/IFrameStrategy.d.ts +49 -0
  47. package/dist/strategies/IFrameStrategy.js +255 -0
  48. package/dist/strategies/KeyboardStrategy.d.ts +35 -0
  49. package/dist/strategies/KeyboardStrategy.js +130 -0
  50. package/dist/strategies/PrintStrategy.d.ts +47 -0
  51. package/dist/strategies/PrintStrategy.js +201 -0
  52. package/dist/strategies/ScreenshotStrategy.d.ts +90 -0
  53. package/dist/strategies/ScreenshotStrategy.js +502 -0
  54. package/dist/strategies/SelectionStrategy.d.ts +49 -0
  55. package/dist/strategies/SelectionStrategy.js +216 -0
  56. package/dist/strategies/WatermarkStrategy.d.ts +56 -0
  57. package/dist/strategies/WatermarkStrategy.js +287 -0
  58. package/dist/strategies/index.d.ts +10 -0
  59. package/dist/strategies/index.js +11 -0
  60. package/dist/types/assessment.d.ts +62 -0
  61. package/dist/types/assessment.js +1 -0
  62. package/dist/types/index.d.ts +278 -0
  63. package/dist/types/index.js +17 -0
  64. package/dist/utils/DOMObserver.d.ts +68 -0
  65. package/dist/utils/DOMObserver.js +134 -0
  66. package/dist/utils/base/LoggableComponent.d.ts +44 -0
  67. package/dist/utils/base/LoggableComponent.js +56 -0
  68. package/dist/utils/detectors/AbstractDevToolsDetector.d.ts +98 -0
  69. package/dist/utils/detectors/AbstractDevToolsDetector.js +127 -0
  70. package/dist/utils/detectors/dateToStringDetector.d.ts +43 -0
  71. package/dist/utils/detectors/dateToStringDetector.js +96 -0
  72. package/dist/utils/detectors/debugLibDetector.d.ts +64 -0
  73. package/dist/utils/detectors/debugLibDetector.js +195 -0
  74. package/dist/utils/detectors/debuggerDetector.d.ts +51 -0
  75. package/dist/utils/detectors/debuggerDetector.js +211 -0
  76. package/dist/utils/detectors/defineGetterDetector.d.ts +48 -0
  77. package/dist/utils/detectors/defineGetterDetector.js +150 -0
  78. package/dist/utils/detectors/detectorInterface.d.ts +36 -0
  79. package/dist/utils/detectors/detectorInterface.js +1 -0
  80. package/dist/utils/detectors/devToolsDetectorManager.d.ts +88 -0
  81. package/dist/utils/detectors/devToolsDetectorManager.js +243 -0
  82. package/dist/utils/detectors/funcToStringDetector.d.ts +43 -0
  83. package/dist/utils/detectors/funcToStringDetector.js +90 -0
  84. package/dist/utils/detectors/regToStringDetector.d.ts +43 -0
  85. package/dist/utils/detectors/regToStringDetector.js +129 -0
  86. package/dist/utils/detectors/sizeDetector.d.ts +54 -0
  87. package/dist/utils/detectors/sizeDetector.js +134 -0
  88. package/dist/utils/detectors/timingDetector.d.ts +55 -0
  89. package/dist/utils/detectors/timingDetector.js +143 -0
  90. package/dist/utils/dom.d.ts +20 -0
  91. package/dist/utils/dom.js +83 -0
  92. package/dist/utils/environment.d.ts +29 -0
  93. package/dist/utils/environment.js +267 -0
  94. package/dist/utils/eventManager.d.ts +162 -0
  95. package/dist/utils/eventManager.js +548 -0
  96. package/dist/utils/index.d.ts +2 -0
  97. package/dist/utils/index.js +3 -0
  98. package/dist/utils/intervalManager.d.ts +91 -0
  99. package/dist/utils/intervalManager.js +221 -0
  100. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.d.ts +41 -0
  101. package/dist/utils/keyboardShortcutManager/keyboardShortcutManager.js +135 -0
  102. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.d.ts +18 -0
  103. package/dist/utils/keyboardShortcutManager/keyboardShortcuts.js +195 -0
  104. package/dist/utils/logging/simple/Loggable.d.ts +33 -0
  105. package/dist/utils/logging/simple/Loggable.js +1 -0
  106. package/dist/utils/logging/simple/LoggingDelegate.d.ts +42 -0
  107. package/dist/utils/logging/simple/LoggingDelegate.js +53 -0
  108. package/dist/utils/logging/simple/SimpleLoggingService.d.ts +39 -0
  109. package/dist/utils/logging/simple/SimpleLoggingService.js +58 -0
  110. package/dist/utils/orientation.d.ts +15 -0
  111. package/dist/utils/orientation.js +32 -0
  112. package/dist/utils/protectedContentManager.d.ts +155 -0
  113. package/dist/utils/protectedContentManager.js +424 -0
  114. package/dist/utils/securityOverlayManager.d.ts +253 -0
  115. package/dist/utils/securityOverlayManager.js +786 -0
  116. package/dist/utils/timeoutManager.d.ts +50 -0
  117. package/dist/utils/timeoutManager.js +113 -0
  118. package/package.json +61 -0
@@ -0,0 +1,314 @@
1
+ import { isBrowser, getBrowser } from "../utils/environment";
2
+ import { intervalManager } from "../utils/intervalManager";
3
+ import { AbstractStrategy, StrategyErrorType } from "./AbstractStrategy";
4
+ import { DevToolsDetectorManager } from "../utils/detectors/devToolsDetectorManager";
5
+ import { ProtectionEventType } from "../core/mediator/protection-event";
6
+ import { timeoutManager } from "../utils/timeoutManager";
7
+ /**
8
+ * Strategy for detecting and responding to DevTools usage
9
+ */
10
+ export class DevToolsStrategy extends AbstractStrategy {
11
+ /**
12
+ * Create a new DevToolsStrategy
13
+ * @param options Options for customizing the DevTools protection
14
+ * @param targetElement Element containing sensitive content
15
+ * @param customHandler Optional custom handler for DevTools detection
16
+ * @param debugMode Enable debug mode for troubleshooting
17
+ */
18
+ constructor(options, targetElement = null, customHandler, debugMode = false) {
19
+ super("DevToolsStrategy", debugMode);
20
+ this.intervalId = null;
21
+ this.taskId = null;
22
+ this.initTimeoutId = null;
23
+ this.isDevToolsOpen = false;
24
+ this.targetElement = null;
25
+ // Detector manager
26
+ this.detectorManager = null;
27
+ this.options = {
28
+ overlayOptions: {
29
+ title: "Developer Tools Detected",
30
+ message: "For security reasons, this content is not available while developer tools are open.",
31
+ secondaryMessage: "Please close developer tools to continue viewing this content.",
32
+ textColor: "white",
33
+ backgroundColor: "rgba(255, 0, 0, 0.7)",
34
+ },
35
+ showOverlay: true,
36
+ checkFrequency: 1000,
37
+ hideContent: false,
38
+ ...options,
39
+ };
40
+ this.targetElement = targetElement;
41
+ this.customHandler = customHandler;
42
+ this.browserInfo = getBrowser();
43
+ this.log("Initialized with checkFrequency:", this.options.checkFrequency);
44
+ this.log("Detected browser:", this.browserInfo.name, this.browserInfo.version);
45
+ // Initialize the detector manager with a slight delay using timeoutManager
46
+ this.initTimeoutId = timeoutManager.setTimeout(`${this.STRATEGY_NAME}-init`, () => {
47
+ this.initDetectorManager();
48
+ this.initTimeoutId = null;
49
+ }, 200);
50
+ }
51
+ /**
52
+ * Initialize the detector manager
53
+ */
54
+ initDetectorManager() {
55
+ return this.safeExecute("initDetectorManager", StrategyErrorType.INITIALIZATION, () => {
56
+ if (!isBrowser())
57
+ return;
58
+ try {
59
+ // Common callback for detector manager
60
+ const onDevToolsChange = (isOpen) => {
61
+ this.handleDevToolsStateChange(isOpen);
62
+ };
63
+ // Get specific detector types if provided in options
64
+ const detectorTypes = this.options.detectorTypes;
65
+ // Initialize the detector manager
66
+ this.detectorManager = new DevToolsDetectorManager({
67
+ onDevToolsChange,
68
+ debugMode: this.debugMode,
69
+ enabledDetectors: detectorTypes,
70
+ checkInterval: this.options.checkFrequency,
71
+ delayInitialCheck: true,
72
+ initialCheckDelay: 1500, // Longer delay for initial check
73
+ });
74
+ this.log("Detector manager initialized");
75
+ }
76
+ catch (error) {
77
+ this.handleError(StrategyErrorType.INITIALIZATION, "Failed to initialize detector manager", error);
78
+ // Log more details about the error to help with troubleshooting
79
+ if (this.debugMode) {
80
+ console.error("Detector manager initialization error details:", error);
81
+ }
82
+ }
83
+ });
84
+ }
85
+ /**
86
+ * Handle DevTools state changes from any detection method
87
+ */
88
+ handleDevToolsStateChange(isOpen) {
89
+ return this.safeExecute("handleDevToolsStateChange", StrategyErrorType.APPLICATION, () => {
90
+ // Only take action if state has changed
91
+ if (isOpen !== this.isDevToolsOpen) {
92
+ this.isDevToolsOpen = isOpen;
93
+ this.log(`DevTools state changed: ${isOpen ? "open" : "closed"}`);
94
+ // Publish the specific DevTools event through the mediator
95
+ if (this.mediator) {
96
+ this.mediator.publish({
97
+ type: ProtectionEventType.DEVTOOLS_STATE_CHANGE,
98
+ source: this.STRATEGY_NAME,
99
+ timestamp: Date.now(),
100
+ data: {
101
+ isOpen,
102
+ showOverlay: this.options.showOverlay,
103
+ overlayOptions: this.options.overlayOptions,
104
+ hideContent: this.options.hideContent,
105
+ target: this.targetElement,
106
+ },
107
+ });
108
+ }
109
+ // Call custom handler if provided
110
+ if (this.customHandler) {
111
+ this.customHandler(isOpen);
112
+ }
113
+ }
114
+ });
115
+ }
116
+ /**
117
+ * Start monitoring for DevTools usage
118
+ */
119
+ startMonitoring() {
120
+ return this.safeExecute("startMonitoring", StrategyErrorType.APPLICATION, () => {
121
+ if (typeof window === "undefined")
122
+ return;
123
+ this.log("Starting DevTools monitoring");
124
+ // Register with IntervalManager for periodic checks
125
+ this.taskId = intervalManager.registerTask("devtools-detection", () => this.safeExecute("intervalTask", StrategyErrorType.APPLICATION, () => {
126
+ // Use the detector manager
127
+ if (this.detectorManager) {
128
+ this.detectorManager.checkDevTools();
129
+ }
130
+ }), this.options.checkFrequency);
131
+ });
132
+ }
133
+ /**
134
+ * Apply the protection strategy
135
+ */
136
+ apply() {
137
+ return this.safeExecute("apply", StrategyErrorType.APPLICATION, () => {
138
+ if (this.isAppliedFlag) {
139
+ this.log("Protection already applied");
140
+ return;
141
+ }
142
+ this.startMonitoring();
143
+ this.isAppliedFlag = true;
144
+ this.log("Protection applied");
145
+ });
146
+ }
147
+ /**
148
+ * Remove the protection strategy
149
+ * Override the base implementation to handle additional cleanup
150
+ */
151
+ remove() {
152
+ return this.safeExecute("remove", StrategyErrorType.REMOVAL, () => {
153
+ if (!this.isAppliedFlag) {
154
+ this.log("Protection not applied");
155
+ return;
156
+ }
157
+ // Clean up the detector manager
158
+ if (this.detectorManager) {
159
+ this.detectorManager.dispose();
160
+ this.detectorManager = null;
161
+ }
162
+ // Clear initialization timeout if it exists
163
+ if (this.initTimeoutId !== null) {
164
+ timeoutManager.clearTimeout(this.initTimeoutId);
165
+ this.initTimeoutId = null;
166
+ }
167
+ // Clear interval via IntervalManager
168
+ if (this.taskId !== null) {
169
+ intervalManager.unregisterTask(this.taskId);
170
+ this.taskId = null;
171
+ this.log("Interval task unregistered");
172
+ }
173
+ // Also clear the old interval for backwards compatibility or if both are used
174
+ if (this.intervalId !== null && typeof window !== "undefined") {
175
+ window.clearInterval(this.intervalId);
176
+ this.intervalId = null;
177
+ this.log("Legacy interval cleared");
178
+ }
179
+ // Call the parent class remove method to handle event cleanup
180
+ super.remove();
181
+ // If DevTools is currently open, publish events to restore content and remove overlay
182
+ if (this.isDevToolsOpen && this.mediator) {
183
+ if (this.options.hideContent) {
184
+ this.mediator.publish({
185
+ type: ProtectionEventType.CONTENT_RESTORED,
186
+ source: this.STRATEGY_NAME,
187
+ timestamp: Date.now(),
188
+ data: {
189
+ strategyName: this.STRATEGY_NAME,
190
+ targetElement: this.targetElement,
191
+ },
192
+ });
193
+ }
194
+ if (this.options.showOverlay) {
195
+ this.mediator.publish({
196
+ type: ProtectionEventType.OVERLAY_REMOVED,
197
+ source: this.STRATEGY_NAME,
198
+ timestamp: Date.now(),
199
+ data: {
200
+ strategyName: this.STRATEGY_NAME,
201
+ overlayType: "devtools",
202
+ reason: "strategy_removed",
203
+ },
204
+ });
205
+ }
206
+ }
207
+ this.isAppliedFlag = false;
208
+ this.isDevToolsOpen = false;
209
+ this.log("Protection removed");
210
+ });
211
+ }
212
+ /**
213
+ * Update DevTools protection options
214
+ * @param options New options
215
+ */
216
+ updateOptions(options) {
217
+ return this.safeExecute("updateOptions", StrategyErrorType.OPTION_UPDATE, () => {
218
+ const typedOptions = options;
219
+ this.log("Updating options", typedOptions);
220
+ // Store previous options for comparison
221
+ const previousOptions = { ...this.options };
222
+ this.options = {
223
+ ...this.options,
224
+ ...typedOptions,
225
+ };
226
+ // If protection is already applied, update the overlay if needed
227
+ if (this.isAppliedFlag && this.isDevToolsOpen && this.mediator) {
228
+ // Check if any visual options changed
229
+ const visualOptionsChanged = previousOptions.overlayOptions?.title !== this.options.overlayOptions?.title ||
230
+ previousOptions.overlayOptions?.message !== this.options.overlayOptions?.message ||
231
+ previousOptions.overlayOptions?.secondaryMessage !== this.options.overlayOptions?.secondaryMessage ||
232
+ previousOptions.overlayOptions?.backgroundColor !== this.options.overlayOptions?.backgroundColor ||
233
+ previousOptions.overlayOptions?.textColor !== this.options.overlayOptions?.textColor;
234
+ if (visualOptionsChanged) {
235
+ // Update overlay through mediator
236
+ if (this.options.showOverlay) {
237
+ this.mediator.publish({
238
+ type: ProtectionEventType.OVERLAY_SHOWN,
239
+ source: this.STRATEGY_NAME,
240
+ timestamp: Date.now(),
241
+ data: {
242
+ strategyName: this.STRATEGY_NAME,
243
+ overlayType: "devtools",
244
+ options: {
245
+ ...this.options.overlayOptions,
246
+ blockEvents: true,
247
+ autoRestore: true,
248
+ },
249
+ priority: 10,
250
+ },
251
+ });
252
+ }
253
+ // Update content through mediator
254
+ if (this.options.hideContent) {
255
+ this.mediator.publish({
256
+ type: ProtectionEventType.CONTENT_HIDDEN,
257
+ source: this.STRATEGY_NAME,
258
+ timestamp: Date.now(),
259
+ data: {
260
+ strategyName: this.STRATEGY_NAME,
261
+ reason: "options_updated",
262
+ options: {
263
+ title: this.options.overlayOptions?.title,
264
+ message: this.options.overlayOptions?.message,
265
+ secondaryMessage: this.options.overlayOptions?.secondaryMessage,
266
+ textColor: "black",
267
+ backgroundColor: "rgba(0, 0, 0, 0.05)",
268
+ },
269
+ targetElement: this.targetElement,
270
+ priority: 10,
271
+ },
272
+ });
273
+ }
274
+ this.log("Reapplied protection with updated visual options");
275
+ }
276
+ }
277
+ // Update check frequency if it changed
278
+ if (typedOptions.checkFrequency &&
279
+ this.taskId !== null &&
280
+ previousOptions.checkFrequency !== typedOptions.checkFrequency) {
281
+ // Unregister and re-register with new frequency
282
+ intervalManager.unregisterTask(this.taskId);
283
+ this.taskId = intervalManager.registerTask("devtools-detection", () => this.safeExecute("intervalTask", StrategyErrorType.APPLICATION, () => {
284
+ // Use detector manager
285
+ if (this.detectorManager) {
286
+ this.detectorManager.checkDevTools();
287
+ }
288
+ }), this.options.checkFrequency);
289
+ this.log(`Check frequency updated to ${this.options.checkFrequency}ms`);
290
+ }
291
+ // If detector types changed, reinitialize the detector manager
292
+ if (typedOptions.detectorTypes && this.detectorManager) {
293
+ this.detectorManager.dispose();
294
+ this.initDetectorManager();
295
+ this.log("Detector manager reinitialized with new detector types");
296
+ }
297
+ });
298
+ }
299
+ /**
300
+ * Set debug mode
301
+ * @param enabled Whether debug mode should be enabled
302
+ */
303
+ setDebugMode(enabled) {
304
+ return this.safeExecute("setDebugMode", StrategyErrorType.OPTION_UPDATE, () => {
305
+ super.setDebugMode(enabled);
306
+ // Update debug mode for the detector manager
307
+ if (this.detectorManager) {
308
+ this.detectorManager.setDebugMode(enabled);
309
+ }
310
+ // Update debug mode for timeoutManager
311
+ timeoutManager.setDebugMode(enabled);
312
+ });
313
+ }
314
+ }
@@ -0,0 +1,66 @@
1
+ import type { BrowserExtensionOptions, CustomEventHandlers } from "../types";
2
+ import { AbstractStrategy } from "./AbstractStrategy";
3
+ /**
4
+ * Strategy for detecting and responding to browser extensions that might scrape content
5
+ */
6
+ export declare class BrowserExtensionDetectionStrategy extends AbstractStrategy {
7
+ private intervalId;
8
+ private taskId;
9
+ private options;
10
+ private extensionsConfig;
11
+ private detectedExtensions;
12
+ private targetElement;
13
+ private configLoaded;
14
+ private configLoadPromise;
15
+ private customHandler?;
16
+ private defaultConfigPath;
17
+ /**
18
+ * Create a new BrowserExtensionDetectionStrategy
19
+ * @param options Configuration options
20
+ * @param targetElement Element containing sensitive content to protect
21
+ * @param customHandler Optional custom handler for extension detection
22
+ * @param debugMode Enable debug mode for troubleshooting
23
+ */
24
+ constructor(options?: BrowserExtensionOptions, targetElement?: HTMLElement | null, customHandler?: CustomEventHandlers["onExtensionDetected"], debugMode?: boolean);
25
+ /**
26
+ * Load extension configuration from a JSON file
27
+ */
28
+ private loadConfiguration;
29
+ /**
30
+ * Apply the protection strategy
31
+ */
32
+ apply(): Promise<void>;
33
+ /**
34
+ * Remove the protection strategy
35
+ */
36
+ remove(): void;
37
+ /**
38
+ * Run all detection methods to check for extensions
39
+ */
40
+ private runAllDetectionMethods;
41
+ /**
42
+ * Detect DOM elements injected by extensions
43
+ */
44
+ private detectDOMInjections;
45
+ /**
46
+ * Check for JavaScript signatures injected by extensions
47
+ */
48
+ private checkJavaScriptSignatures;
49
+ /**
50
+ * Check if a property exists in an object, supporting dot notation
51
+ */
52
+ private checkPropertyExists;
53
+ /**
54
+ * Handle detection of an extension
55
+ */
56
+ private handleDetection;
57
+ /**
58
+ * Update options for the strategy
59
+ */
60
+ updateOptions(options: Record<string, unknown>): void;
61
+ /**
62
+ * Set debug mode
63
+ * @param enabled Whether debug mode should be enabled
64
+ */
65
+ setDebugMode(enabled: boolean): void;
66
+ }