@dynamicu/chromedebug-mcp 2.2.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 (95) hide show
  1. package/CLAUDE.md +344 -0
  2. package/LICENSE +21 -0
  3. package/README.md +250 -0
  4. package/chrome-extension/README.md +41 -0
  5. package/chrome-extension/background.js +3917 -0
  6. package/chrome-extension/chrome-session-manager.js +706 -0
  7. package/chrome-extension/content.css +181 -0
  8. package/chrome-extension/content.js +3022 -0
  9. package/chrome-extension/data-buffer.js +435 -0
  10. package/chrome-extension/dom-tracker.js +411 -0
  11. package/chrome-extension/extension-config.js +78 -0
  12. package/chrome-extension/firebase-client.js +278 -0
  13. package/chrome-extension/firebase-config.js +32 -0
  14. package/chrome-extension/firebase-config.module.js +22 -0
  15. package/chrome-extension/firebase-config.module.template.js +27 -0
  16. package/chrome-extension/firebase-config.template.js +36 -0
  17. package/chrome-extension/frame-capture.js +407 -0
  18. package/chrome-extension/icon128.png +1 -0
  19. package/chrome-extension/icon16.png +1 -0
  20. package/chrome-extension/icon48.png +1 -0
  21. package/chrome-extension/license-helper.js +181 -0
  22. package/chrome-extension/logger.js +23 -0
  23. package/chrome-extension/manifest.json +73 -0
  24. package/chrome-extension/network-tracker.js +510 -0
  25. package/chrome-extension/offscreen.html +10 -0
  26. package/chrome-extension/options.html +203 -0
  27. package/chrome-extension/options.js +282 -0
  28. package/chrome-extension/pako.min.js +2 -0
  29. package/chrome-extension/performance-monitor.js +533 -0
  30. package/chrome-extension/pii-redactor.js +405 -0
  31. package/chrome-extension/popup.html +532 -0
  32. package/chrome-extension/popup.js +2446 -0
  33. package/chrome-extension/upload-manager.js +323 -0
  34. package/chrome-extension/web-vitals.iife.js +1 -0
  35. package/config/api-keys.json +11 -0
  36. package/config/chrome-pilot-config.json +45 -0
  37. package/package.json +126 -0
  38. package/scripts/cleanup-processes.js +109 -0
  39. package/scripts/config-manager.js +280 -0
  40. package/scripts/generate-extension-config.js +53 -0
  41. package/scripts/setup-security.js +64 -0
  42. package/src/capture/architecture.js +426 -0
  43. package/src/capture/error-handling-tests.md +38 -0
  44. package/src/capture/error-handling-types.ts +360 -0
  45. package/src/capture/index.js +508 -0
  46. package/src/capture/interfaces.js +625 -0
  47. package/src/capture/memory-manager.js +713 -0
  48. package/src/capture/types.js +342 -0
  49. package/src/chrome-controller.js +2658 -0
  50. package/src/cli.js +19 -0
  51. package/src/config-loader.js +303 -0
  52. package/src/database.js +2178 -0
  53. package/src/firebase-license-manager.js +462 -0
  54. package/src/firebase-privacy-guard.js +397 -0
  55. package/src/http-server.js +1516 -0
  56. package/src/index-direct.js +157 -0
  57. package/src/index-modular.js +219 -0
  58. package/src/index-monolithic-backup.js +2230 -0
  59. package/src/index.js +305 -0
  60. package/src/legacy/chrome-controller-old.js +1406 -0
  61. package/src/legacy/index-express.js +625 -0
  62. package/src/legacy/index-old.js +977 -0
  63. package/src/legacy/routes.js +260 -0
  64. package/src/legacy/shared-storage.js +101 -0
  65. package/src/logger.js +10 -0
  66. package/src/mcp/handlers/chrome-tool-handler.js +306 -0
  67. package/src/mcp/handlers/element-tool-handler.js +51 -0
  68. package/src/mcp/handlers/frame-tool-handler.js +957 -0
  69. package/src/mcp/handlers/request-handler.js +104 -0
  70. package/src/mcp/handlers/workflow-tool-handler.js +636 -0
  71. package/src/mcp/server.js +68 -0
  72. package/src/mcp/tools/index.js +701 -0
  73. package/src/middleware/auth.js +371 -0
  74. package/src/middleware/security.js +267 -0
  75. package/src/port-discovery.js +258 -0
  76. package/src/routes/admin.js +182 -0
  77. package/src/services/browser-daemon.js +494 -0
  78. package/src/services/chrome-service.js +375 -0
  79. package/src/services/failover-manager.js +412 -0
  80. package/src/services/git-safety-service.js +675 -0
  81. package/src/services/heartbeat-manager.js +200 -0
  82. package/src/services/http-client.js +195 -0
  83. package/src/services/process-manager.js +318 -0
  84. package/src/services/process-tracker.js +574 -0
  85. package/src/services/profile-manager.js +449 -0
  86. package/src/services/project-manager.js +415 -0
  87. package/src/services/session-manager.js +497 -0
  88. package/src/services/session-registry.js +491 -0
  89. package/src/services/unified-session-manager.js +678 -0
  90. package/src/shared-storage-old.js +267 -0
  91. package/src/standalone-server.js +53 -0
  92. package/src/utils/extension-path.js +145 -0
  93. package/src/utils.js +187 -0
  94. package/src/validation/log-transformer.js +125 -0
  95. package/src/validation/schemas.js +391 -0
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Firebase Privacy Guard
3
+ *
4
+ * CRITICAL SECURITY MODULE - Prevents sensitive recording data from being sent to Firebase
5
+ *
6
+ * This module acts as a gatekeeper to ensure that ONLY licensing-related data
7
+ * is transmitted to Firebase. Any attempt to send recording data will be blocked
8
+ * and logged as a security violation.
9
+ *
10
+ * STRICT PRIVACY RULES:
11
+ * 1. Only whitelisted fields are allowed through
12
+ * 2. Any forbidden field triggers immediate rejection
13
+ * 3. All violations are logged for audit
14
+ * 4. No recording, frame, DOM, or network data ever leaves the local system
15
+ */
16
+
17
+ /**
18
+ * Whitelist of allowed fields for Firebase transmission
19
+ * ONLY these fields are permitted in any Firebase operation
20
+ */
21
+ const ALLOWED_FIELDS = new Set([
22
+ // User identification
23
+ 'userId',
24
+ 'email',
25
+ 'displayName',
26
+
27
+ // License data
28
+ 'licenseKey',
29
+ 'tier',
30
+ 'status',
31
+ 'expiresAt',
32
+ 'createdAt',
33
+ 'updatedAt',
34
+
35
+ // Instance tracking (for anti-sharing)
36
+ 'instanceId',
37
+ 'deviceName',
38
+ 'platform',
39
+ 'lastSeen',
40
+
41
+ // Usage metrics (counts only, no content)
42
+ 'count',
43
+ 'timestamp',
44
+ 'date',
45
+ 'usageCount',
46
+ 'dailyUsage',
47
+
48
+ // Metadata (generic container fields)
49
+ 'id',
50
+ 'type',
51
+ 'version',
52
+ 'metadata'
53
+ ]);
54
+
55
+ /**
56
+ * Forbidden fields that indicate recording/sensitive data
57
+ * NEVER allowed in Firebase operations
58
+ */
59
+ const FORBIDDEN_FIELDS = new Set([
60
+ // Recording data
61
+ 'recordings',
62
+ 'frames',
63
+ 'frameData',
64
+ 'imageData',
65
+ 'screenshot',
66
+ 'video',
67
+
68
+ // Console and logs
69
+ 'consoleLogs',
70
+ 'logs',
71
+ 'errorLogs',
72
+ 'debugLogs',
73
+
74
+ // DOM and page content
75
+ 'domSnapshots',
76
+ 'dom',
77
+ 'html',
78
+ 'content',
79
+ 'pageContent',
80
+ 'domMutations',
81
+
82
+ // Network data
83
+ 'networkRequests',
84
+ 'requests',
85
+ 'responses',
86
+ 'headers',
87
+ 'body',
88
+ 'payload',
89
+
90
+ // Browser state
91
+ 'cookies',
92
+ 'localStorage',
93
+ 'sessionStorage',
94
+ 'storage',
95
+
96
+ // User interactions
97
+ 'interactions',
98
+ 'clicks',
99
+ 'inputs',
100
+ 'keystrokes',
101
+
102
+ // Code and execution
103
+ 'code',
104
+ 'script',
105
+ 'function',
106
+ 'execution',
107
+ 'trace',
108
+ 'stack',
109
+
110
+ // Sensitive metadata
111
+ 'url',
112
+ 'path',
113
+ 'query',
114
+ 'params'
115
+ ]);
116
+
117
+ /**
118
+ * Privacy violation tracker
119
+ */
120
+ class PrivacyViolationLogger {
121
+ constructor() {
122
+ this.violations = [];
123
+ }
124
+
125
+ log(violation) {
126
+ const entry = {
127
+ timestamp: new Date().toISOString(),
128
+ ...violation
129
+ };
130
+ this.violations.push(entry);
131
+ console.error('[PRIVACY VIOLATION]', JSON.stringify(entry, null, 2));
132
+ }
133
+
134
+ getViolations() {
135
+ return this.violations;
136
+ }
137
+
138
+ clear() {
139
+ this.violations = [];
140
+ }
141
+ }
142
+
143
+ const violationLogger = new PrivacyViolationLogger();
144
+
145
+ /**
146
+ * Firebase Privacy Guard Class
147
+ */
148
+ export class FirebasePrivacyGuard {
149
+ /**
150
+ * Sanitize data before Firebase transmission
151
+ * Removes any non-whitelisted fields and validates against forbidden fields
152
+ *
153
+ * @param {Object} data - Data to sanitize
154
+ * @param {string} context - Context of the operation (for logging)
155
+ * @returns {Object} - Sanitized data with only allowed fields
156
+ * @throws {Error} - If forbidden fields are detected
157
+ */
158
+ static sanitize(data, context = 'unknown') {
159
+ if (!data || typeof data !== 'object') {
160
+ return data;
161
+ }
162
+
163
+ // Handle arrays
164
+ if (Array.isArray(data)) {
165
+ return data.map(item => this.sanitize(item, context));
166
+ }
167
+
168
+ const sanitized = {};
169
+ const violations = [];
170
+
171
+ // First pass: check for forbidden fields anywhere in the tree
172
+ const checkForbidden = (obj, path = '') => {
173
+ for (const [key, value] of Object.entries(obj)) {
174
+ const fullPath = path ? `${path}.${key}` : key;
175
+
176
+ if (FORBIDDEN_FIELDS.has(key)) {
177
+ violations.push({
178
+ field: fullPath,
179
+ type: 'FORBIDDEN_FIELD',
180
+ context,
181
+ severity: 'CRITICAL'
182
+ });
183
+ }
184
+
185
+ // Check nested objects
186
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
187
+ checkForbidden(value, fullPath);
188
+ }
189
+
190
+ // Check arrays
191
+ if (Array.isArray(value)) {
192
+ value.forEach((item, index) => {
193
+ if (item && typeof item === 'object') {
194
+ checkForbidden(item, `${fullPath}[${index}]`);
195
+ }
196
+ });
197
+ }
198
+ }
199
+ };
200
+
201
+ checkForbidden(data);
202
+
203
+ // If forbidden fields found, throw immediately
204
+ const criticalViolations = violations.filter(v => v.severity === 'CRITICAL');
205
+ if (criticalViolations.length > 0) {
206
+ violationLogger.log({
207
+ operation: 'sanitize',
208
+ context,
209
+ violations,
210
+ originalFields: Object.keys(data),
211
+ sanitizedFields: []
212
+ });
213
+
214
+ throw new Error(
215
+ `Privacy violation: Forbidden fields detected in Firebase operation: ${
216
+ criticalViolations.map(v => v.field).join(', ')
217
+ }`
218
+ );
219
+ }
220
+
221
+ // Second pass: build sanitized object with only allowed fields
222
+ for (const [key, value] of Object.entries(data)) {
223
+ // Only include whitelisted fields
224
+ if (ALLOWED_FIELDS.has(key)) {
225
+ // Recursively sanitize nested objects
226
+ if (value && typeof value === 'object') {
227
+ sanitized[key] = this.sanitize(value, `${context}.${key}`);
228
+ } else {
229
+ sanitized[key] = value;
230
+ }
231
+ } else {
232
+ // Non-whitelisted field (not forbidden, just unknown)
233
+ violations.push({
234
+ field: key,
235
+ type: 'NON_WHITELISTED',
236
+ context,
237
+ severity: 'WARNING'
238
+ });
239
+ }
240
+ }
241
+
242
+ // Log violations
243
+ if (violations.length > 0) {
244
+ violationLogger.log({
245
+ operation: 'sanitize',
246
+ context,
247
+ violations,
248
+ originalFields: Object.keys(data),
249
+ sanitizedFields: Object.keys(sanitized)
250
+ });
251
+
252
+ // Throw error if critical violations detected
253
+ const criticalViolations = violations.filter(v => v.severity === 'CRITICAL');
254
+ if (criticalViolations.length > 0) {
255
+ throw new Error(
256
+ `Privacy violation: Forbidden fields detected in Firebase operation: ${
257
+ criticalViolations.map(v => v.field).join(', ')
258
+ }`
259
+ );
260
+ }
261
+ }
262
+
263
+ return sanitized;
264
+ }
265
+
266
+ /**
267
+ * Validate data before Firebase transmission
268
+ * Does NOT modify data, only validates
269
+ *
270
+ * @param {Object} data - Data to validate
271
+ * @param {string} context - Context of the operation
272
+ * @returns {Object} - Validation result
273
+ */
274
+ static validate(data, context = 'unknown') {
275
+ if (!data || typeof data !== 'object') {
276
+ return { valid: true, violations: [] };
277
+ }
278
+
279
+ const violations = [];
280
+ const checkObject = (obj, path = '') => {
281
+ for (const [key, value] of Object.entries(obj)) {
282
+ const fullPath = path ? `${path}.${key}` : key;
283
+
284
+ // Check for forbidden fields
285
+ if (FORBIDDEN_FIELDS.has(key)) {
286
+ violations.push({
287
+ field: fullPath,
288
+ type: 'FORBIDDEN_FIELD',
289
+ severity: 'CRITICAL'
290
+ });
291
+ }
292
+
293
+ // Check nested objects
294
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
295
+ checkObject(value, fullPath);
296
+ }
297
+
298
+ // Check arrays
299
+ if (Array.isArray(value)) {
300
+ value.forEach((item, index) => {
301
+ if (item && typeof item === 'object') {
302
+ checkObject(item, `${fullPath}[${index}]`);
303
+ }
304
+ });
305
+ }
306
+ }
307
+ };
308
+
309
+ checkObject(data);
310
+
311
+ if (violations.length > 0) {
312
+ violationLogger.log({
313
+ operation: 'validate',
314
+ context,
315
+ violations
316
+ });
317
+ }
318
+
319
+ return {
320
+ valid: violations.filter(v => v.severity === 'CRITICAL').length === 0,
321
+ violations,
322
+ hasCriticalViolations: violations.some(v => v.severity === 'CRITICAL'),
323
+ hasWarnings: violations.some(v => v.severity === 'WARNING')
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Assert that data is safe for Firebase
329
+ * Throws error if validation fails
330
+ *
331
+ * @param {Object} data - Data to check
332
+ * @param {string} context - Context of the operation
333
+ */
334
+ static assertSafe(data, context = 'unknown') {
335
+ const validation = this.validate(data, context);
336
+
337
+ if (!validation.valid) {
338
+ const criticalFields = validation.violations
339
+ .filter(v => v.severity === 'CRITICAL')
340
+ .map(v => v.field)
341
+ .join(', ');
342
+
343
+ throw new Error(
344
+ `Firebase Privacy Guard: Forbidden data detected in ${context}. ` +
345
+ `Attempted to send: ${criticalFields}. ` +
346
+ `This operation has been blocked for security.`
347
+ );
348
+ }
349
+
350
+ return true;
351
+ }
352
+
353
+ /**
354
+ * Get privacy violation history
355
+ */
356
+ static getViolations() {
357
+ return violationLogger.getViolations();
358
+ }
359
+
360
+ /**
361
+ * Clear violation history (for testing)
362
+ */
363
+ static clearViolations() {
364
+ violationLogger.clear();
365
+ }
366
+
367
+ /**
368
+ * Check if a field is allowed
369
+ */
370
+ static isAllowedField(fieldName) {
371
+ return ALLOWED_FIELDS.has(fieldName);
372
+ }
373
+
374
+ /**
375
+ * Check if a field is forbidden
376
+ */
377
+ static isForbiddenField(fieldName) {
378
+ return FORBIDDEN_FIELDS.has(fieldName);
379
+ }
380
+
381
+ /**
382
+ * Get list of allowed fields
383
+ */
384
+ static getAllowedFields() {
385
+ return Array.from(ALLOWED_FIELDS);
386
+ }
387
+
388
+ /**
389
+ * Get list of forbidden fields
390
+ */
391
+ static getForbiddenFields() {
392
+ return Array.from(FORBIDDEN_FIELDS);
393
+ }
394
+ }
395
+
396
+ // Export for testing
397
+ export { ALLOWED_FIELDS, FORBIDDEN_FIELDS, violationLogger };