guardrail-compliance 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.
Files changed (149) hide show
  1. package/dist/audit/emitter.d.ts +97 -0
  2. package/dist/audit/emitter.d.ts.map +1 -0
  3. package/dist/audit/emitter.js +197 -0
  4. package/dist/audit/events.d.ts +304 -0
  5. package/dist/audit/events.d.ts.map +1 -0
  6. package/dist/audit/events.js +267 -0
  7. package/dist/audit/index.d.ts +11 -0
  8. package/dist/audit/index.d.ts.map +1 -0
  9. package/dist/audit/index.js +51 -0
  10. package/dist/audit/storage.d.ts +93 -0
  11. package/dist/audit/storage.d.ts.map +1 -0
  12. package/dist/audit/storage.js +337 -0
  13. package/dist/automation/__tests__/compliance-scheduler.test.d.ts +2 -0
  14. package/dist/automation/__tests__/compliance-scheduler.test.d.ts.map +1 -0
  15. package/dist/automation/__tests__/compliance-scheduler.test.js +140 -0
  16. package/dist/automation/audit-logger.d.ts +129 -0
  17. package/dist/automation/audit-logger.d.ts.map +1 -0
  18. package/dist/automation/audit-logger.js +473 -0
  19. package/dist/automation/compliance-scheduler-fixed.d.ts +1 -0
  20. package/dist/automation/compliance-scheduler-fixed.d.ts.map +1 -0
  21. package/dist/automation/compliance-scheduler-fixed.js +1 -0
  22. package/dist/automation/compliance-scheduler.d.ts +83 -0
  23. package/dist/automation/compliance-scheduler.d.ts.map +1 -0
  24. package/dist/automation/compliance-scheduler.js +414 -0
  25. package/dist/automation/dashboard.d.ts +194 -0
  26. package/dist/automation/dashboard.d.ts.map +1 -0
  27. package/dist/automation/dashboard.js +768 -0
  28. package/dist/automation/email-service.d.ts +69 -0
  29. package/dist/automation/email-service.d.ts.map +1 -0
  30. package/dist/automation/email-service.js +218 -0
  31. package/dist/automation/evidence-collector.d.ts +140 -0
  32. package/dist/automation/evidence-collector.d.ts.map +1 -0
  33. package/dist/automation/evidence-collector.js +682 -0
  34. package/dist/automation/index.d.ts +8 -0
  35. package/dist/automation/index.d.ts.map +1 -0
  36. package/dist/automation/index.js +24 -0
  37. package/dist/automation/pdf-exporter.d.ts +90 -0
  38. package/dist/automation/pdf-exporter.d.ts.map +1 -0
  39. package/dist/automation/pdf-exporter.js +381 -0
  40. package/dist/automation/reporting-engine.d.ts +116 -0
  41. package/dist/automation/reporting-engine.d.ts.map +1 -0
  42. package/dist/automation/reporting-engine.js +329 -0
  43. package/dist/container/index.d.ts +4 -0
  44. package/dist/container/index.d.ts.map +1 -0
  45. package/dist/container/index.js +19 -0
  46. package/dist/container/kubernetes.d.ts +94 -0
  47. package/dist/container/kubernetes.d.ts.map +1 -0
  48. package/dist/container/kubernetes.js +268 -0
  49. package/dist/container/rules.d.ts +27 -0
  50. package/dist/container/rules.d.ts.map +1 -0
  51. package/dist/container/rules.js +216 -0
  52. package/dist/container/scanner.d.ts +50 -0
  53. package/dist/container/scanner.d.ts.map +1 -0
  54. package/dist/container/scanner.js +143 -0
  55. package/dist/frameworks/engine.d.ts +108 -0
  56. package/dist/frameworks/engine.d.ts.map +1 -0
  57. package/dist/frameworks/engine.js +206 -0
  58. package/dist/frameworks/gdpr.d.ts +6 -0
  59. package/dist/frameworks/gdpr.d.ts.map +1 -0
  60. package/dist/frameworks/gdpr.js +198 -0
  61. package/dist/frameworks/hipaa.d.ts +6 -0
  62. package/dist/frameworks/hipaa.d.ts.map +1 -0
  63. package/dist/frameworks/hipaa.js +183 -0
  64. package/dist/frameworks/index.d.ts +8 -0
  65. package/dist/frameworks/index.d.ts.map +1 -0
  66. package/dist/frameworks/index.js +30 -0
  67. package/dist/frameworks/iso27001.d.ts +63 -0
  68. package/dist/frameworks/iso27001.d.ts.map +1 -0
  69. package/dist/frameworks/iso27001.js +331 -0
  70. package/dist/frameworks/nist.d.ts +62 -0
  71. package/dist/frameworks/nist.d.ts.map +1 -0
  72. package/dist/frameworks/nist.js +424 -0
  73. package/dist/frameworks/pci.d.ts +6 -0
  74. package/dist/frameworks/pci.d.ts.map +1 -0
  75. package/dist/frameworks/pci.js +201 -0
  76. package/dist/frameworks/soc2.d.ts +7 -0
  77. package/dist/frameworks/soc2.d.ts.map +1 -0
  78. package/dist/frameworks/soc2.js +248 -0
  79. package/dist/iac/drift-detector.d.ts +64 -0
  80. package/dist/iac/drift-detector.d.ts.map +1 -0
  81. package/dist/iac/drift-detector.js +134 -0
  82. package/dist/iac/index.d.ts +4 -0
  83. package/dist/iac/index.d.ts.map +1 -0
  84. package/dist/iac/index.js +19 -0
  85. package/dist/iac/rules.d.ts +17 -0
  86. package/dist/iac/rules.d.ts.map +1 -0
  87. package/dist/iac/rules.js +385 -0
  88. package/dist/iac/scanner.d.ts +104 -0
  89. package/dist/iac/scanner.d.ts.map +1 -0
  90. package/dist/iac/scanner.js +343 -0
  91. package/dist/index.d.ts +7 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +28 -0
  94. package/dist/pii/data-flow.d.ts +58 -0
  95. package/dist/pii/data-flow.d.ts.map +1 -0
  96. package/dist/pii/data-flow.js +154 -0
  97. package/dist/pii/detector.d.ts +60 -0
  98. package/dist/pii/detector.d.ts.map +1 -0
  99. package/dist/pii/detector.js +267 -0
  100. package/dist/pii/index.d.ts +4 -0
  101. package/dist/pii/index.d.ts.map +1 -0
  102. package/dist/pii/index.js +19 -0
  103. package/dist/pii/patterns.d.ts +36 -0
  104. package/dist/pii/patterns.d.ts.map +1 -0
  105. package/dist/pii/patterns.js +108 -0
  106. package/dist/policy/index.d.ts +5 -0
  107. package/dist/policy/index.d.ts.map +1 -0
  108. package/dist/policy/index.js +20 -0
  109. package/dist/policy/opa-engine.d.ts +121 -0
  110. package/dist/policy/opa-engine.d.ts.map +1 -0
  111. package/dist/policy/opa-engine.js +423 -0
  112. package/package.json +31 -0
  113. package/src/audit/emitter.ts +383 -0
  114. package/src/audit/events.ts +351 -0
  115. package/src/audit/index.ts +35 -0
  116. package/src/audit/storage.ts +394 -0
  117. package/src/automation/__tests__/compliance-scheduler.test.ts +183 -0
  118. package/src/automation/audit-logger.ts +629 -0
  119. package/src/automation/compliance-scheduler-fixed.ts +0 -0
  120. package/src/automation/compliance-scheduler.ts +516 -0
  121. package/src/automation/dashboard.ts +947 -0
  122. package/src/automation/email-service.ts +230 -0
  123. package/src/automation/evidence-collector.ts +866 -0
  124. package/src/automation/index.ts +8 -0
  125. package/src/automation/pdf-exporter.ts +434 -0
  126. package/src/automation/reporting-engine.ts +462 -0
  127. package/src/container/index.ts +3 -0
  128. package/src/container/kubernetes.ts +379 -0
  129. package/src/container/rules.ts +244 -0
  130. package/src/container/scanner.ts +202 -0
  131. package/src/frameworks/engine.ts +298 -0
  132. package/src/frameworks/gdpr.ts +204 -0
  133. package/src/frameworks/hipaa.ts +209 -0
  134. package/src/frameworks/index.ts +23 -0
  135. package/src/frameworks/iso27001.ts +398 -0
  136. package/src/frameworks/nist.ts +518 -0
  137. package/src/frameworks/pci.ts +226 -0
  138. package/src/frameworks/soc2.ts +281 -0
  139. package/src/iac/drift-detector.ts +197 -0
  140. package/src/iac/index.ts +3 -0
  141. package/src/iac/rules.ts +420 -0
  142. package/src/iac/scanner.ts +445 -0
  143. package/src/index.ts +17 -0
  144. package/src/pii/data-flow.ts +216 -0
  145. package/src/pii/detector.ts +327 -0
  146. package/src/pii/index.ts +3 -0
  147. package/src/pii/patterns.ts +128 -0
  148. package/src/policy/index.ts +5 -0
  149. package/src/policy/opa-engine.ts +504 -0
@@ -0,0 +1,343 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.iacSecurityScanner = exports.IaCSecurityScanner = void 0;
4
+ const database_1 = require("@guardrail/database");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const rules_1 = require("./rules");
8
+ const drift_detector_1 = require("./drift-detector");
9
+ class IaCSecurityScanner {
10
+ /**
11
+ * Main scan function
12
+ */
13
+ async scan(projectPath, projectId) {
14
+ const providers = [];
15
+ const allResources = [];
16
+ // Find and parse Terraform files
17
+ const tfFiles = this.findFiles(projectPath, '.tf');
18
+ if (tfFiles.length > 0) {
19
+ providers.push('terraform');
20
+ for (const file of tfFiles) {
21
+ const resources = await this.parseTerraform([file]);
22
+ resources.forEach(r => allResources.push({ resource: r, filePath: file, provider: 'terraform' }));
23
+ }
24
+ }
25
+ // Find and parse CloudFormation templates
26
+ const cfnFiles = this.findFiles(projectPath, '.yaml', '.yml', '.json').filter(f => f.includes('cloudformation') || f.includes('template'));
27
+ if (cfnFiles.length > 0) {
28
+ providers.push('cloudformation');
29
+ for (const file of cfnFiles) {
30
+ const resources = await this.parseCloudFormation(file);
31
+ resources.forEach(r => allResources.push({ resource: r, filePath: file, provider: 'cloudformation' }));
32
+ }
33
+ }
34
+ // Find and parse Kubernetes manifests
35
+ const k8sFiles = this.findFiles(projectPath, '.yaml', '.yml').filter(f => !f.includes('cloudformation') && !f.includes('template'));
36
+ if (k8sFiles.length > 0) {
37
+ const k8sResources = await this.parseKubernetes(k8sFiles);
38
+ if (k8sResources.length > 0) {
39
+ providers.push('kubernetes');
40
+ k8sResources.forEach((r, i) => allResources.push({ resource: r, filePath: k8sFiles[i % k8sFiles.length] || 'unknown', provider: 'kubernetes' }));
41
+ }
42
+ }
43
+ // Scan all resources against rules
44
+ const findings = this.scanResources(allResources);
45
+ // Calculate summary
46
+ const summary = {
47
+ total: findings.length,
48
+ critical: findings.filter(f => f.severity === 'critical').length,
49
+ high: findings.filter(f => f.severity === 'high').length,
50
+ medium: findings.filter(f => f.severity === 'medium').length,
51
+ low: findings.filter(f => f.severity === 'low').length
52
+ };
53
+ // Detect drift if Terraform is used
54
+ let driftReport;
55
+ if (providers.includes('terraform')) {
56
+ driftReport = await drift_detector_1.driftDetector.detectDrift(projectPath);
57
+ }
58
+ // Analyze costs
59
+ const costAnalysis = await this.analyzeCosts(findings);
60
+ // Save to database
61
+ try {
62
+ await database_1.prisma.iaCScan.create({
63
+ data: {
64
+ projectId
65
+ }
66
+ });
67
+ }
68
+ catch (error) {
69
+ // Table may not exist - continue
70
+ }
71
+ return {
72
+ projectId,
73
+ providers,
74
+ summary,
75
+ findings,
76
+ driftReport,
77
+ costAnalysis
78
+ };
79
+ }
80
+ /**
81
+ * Parse Terraform files
82
+ */
83
+ async parseTerraform(files) {
84
+ const resources = [];
85
+ for (const file of files) {
86
+ try {
87
+ const content = (0, fs_1.readFileSync)(file, 'utf-8');
88
+ // Simple HCL parsing (in production, use proper HCL parser)
89
+ const resourceMatches = content.matchAll(/resource\s+"([^"]+)"\s+"([^"]+)"\s+{([^}]*)}/gs);
90
+ for (const match of resourceMatches) {
91
+ const [, type, name, configBlock] = match;
92
+ if (!type || !name)
93
+ continue;
94
+ // Parse config block (simplified)
95
+ const config = {};
96
+ const lines = (configBlock || '').split('\n');
97
+ for (const line of lines) {
98
+ const keyValue = line.match(/^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/);
99
+ if (keyValue) {
100
+ const [, key, value] = keyValue;
101
+ if (key && value) {
102
+ config[key.trim()] = this.parseValue(value.trim());
103
+ }
104
+ }
105
+ }
106
+ resources.push({
107
+ type,
108
+ name,
109
+ provider: type.split('_')[0] || 'unknown', // e.g., 'aws' from 'aws_s3_bucket'
110
+ config
111
+ });
112
+ }
113
+ }
114
+ catch (error) {
115
+ console.error(`Error parsing Terraform file ${file}:`, error);
116
+ }
117
+ }
118
+ return resources;
119
+ }
120
+ /**
121
+ * Parse CloudFormation template
122
+ */
123
+ async parseCloudFormation(file) {
124
+ const resources = [];
125
+ try {
126
+ const content = (0, fs_1.readFileSync)(file, 'utf-8');
127
+ const template = file.endsWith('.json') ? JSON.parse(content) : this.parseYAML(content);
128
+ if (template.Resources) {
129
+ for (const [logicalId, resource] of Object.entries(template.Resources)) {
130
+ resources.push({
131
+ type: resource.Type,
132
+ logicalId,
133
+ properties: resource.Properties || {}
134
+ });
135
+ }
136
+ }
137
+ }
138
+ catch (error) {
139
+ console.error(`Error parsing CloudFormation file ${file}:`, error);
140
+ }
141
+ return resources;
142
+ }
143
+ /**
144
+ * Parse Kubernetes manifests
145
+ */
146
+ async parseKubernetes(files) {
147
+ const resources = [];
148
+ for (const file of files) {
149
+ try {
150
+ const content = (0, fs_1.readFileSync)(file, 'utf-8');
151
+ const manifests = this.parseYAML(content);
152
+ // Handle both single manifest and array of manifests
153
+ const manifestArray = Array.isArray(manifests) ? manifests : [manifests];
154
+ for (const manifest of manifestArray) {
155
+ if (manifest && manifest.kind && manifest.metadata) {
156
+ resources.push({
157
+ apiVersion: manifest.apiVersion || '',
158
+ kind: manifest.kind,
159
+ metadata: manifest.metadata,
160
+ spec: manifest.spec || {}
161
+ });
162
+ }
163
+ }
164
+ }
165
+ catch (error) {
166
+ console.error(`Error parsing Kubernetes file ${file}:`, error);
167
+ }
168
+ }
169
+ return resources;
170
+ }
171
+ /**
172
+ * Scan resources against rules
173
+ */
174
+ scanResources(resources) {
175
+ const findings = [];
176
+ for (const { resource, filePath, provider } of resources) {
177
+ // Get applicable rules
178
+ const rules = rules_1.ALL_RULES.filter(rule => {
179
+ if (provider === 'terraform') {
180
+ const tfResource = resource;
181
+ return rule.provider === 'terraform' && rule.resourceType === tfResource.type;
182
+ }
183
+ else if (provider === 'kubernetes') {
184
+ const k8sResource = resource;
185
+ return rule.provider === 'kubernetes' && rule.resourceType === k8sResource.kind;
186
+ }
187
+ else if (provider === 'cloudformation') {
188
+ const cfnResource = resource;
189
+ return rule.resourceType === cfnResource.type;
190
+ }
191
+ return false;
192
+ });
193
+ // Check each rule
194
+ for (const rule of rules) {
195
+ try {
196
+ const resourceData = this.getResourceData(resource, provider);
197
+ const violates = rule.check(resourceData);
198
+ if (violates) {
199
+ findings.push({
200
+ ruleId: rule.id,
201
+ severity: rule.severity,
202
+ category: rule.category,
203
+ title: rule.title,
204
+ description: rule.description,
205
+ resourceType: this.getResourceType(resource, provider),
206
+ resourceName: this.getResourceName(resource, provider),
207
+ filePath,
208
+ recommendation: rule.recommendation
209
+ });
210
+ }
211
+ }
212
+ catch (error) {
213
+ console.error(`Error checking rule ${rule.id}:`, error);
214
+ }
215
+ }
216
+ }
217
+ return findings;
218
+ }
219
+ /**
220
+ * Analyze costs based on findings
221
+ */
222
+ async analyzeCosts(findings) {
223
+ const costByService = {};
224
+ const suggestions = [];
225
+ // Estimate costs based on security findings
226
+ // In production, this would use cloud provider pricing APIs
227
+ // Example: unencrypted resources cost more due to compliance requirements
228
+ const encryptionFindings = findings.filter(f => f.description.toLowerCase().includes('encryption'));
229
+ if (encryptionFindings.length > 0) {
230
+ suggestions.push(`Enable encryption on ${encryptionFindings.length} resources to reduce compliance costs`);
231
+ }
232
+ // Public resources may incur data transfer costs
233
+ const publicFindings = findings.filter(f => f.description.toLowerCase().includes('public'));
234
+ if (publicFindings.length > 0) {
235
+ suggestions.push(`Restrict ${publicFindings.length} public resources to reduce data transfer costs`);
236
+ }
237
+ return {
238
+ estimatedMonthlyCost: 0, // Would calculate actual costs in production
239
+ costByService,
240
+ costOptimizationSuggestions: suggestions
241
+ };
242
+ }
243
+ /**
244
+ * Find files with specific extensions recursively
245
+ */
246
+ findFiles(dir, ...extensions) {
247
+ const files = [];
248
+ try {
249
+ const entries = (0, fs_1.readdirSync)(dir);
250
+ for (const entry of entries) {
251
+ const fullPath = (0, path_1.join)(dir, entry);
252
+ const stat = (0, fs_1.statSync)(fullPath);
253
+ if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {
254
+ files.push(...this.findFiles(fullPath, ...extensions));
255
+ }
256
+ else if (stat.isFile()) {
257
+ if (extensions.some(ext => entry.endsWith(ext))) {
258
+ files.push(fullPath);
259
+ }
260
+ }
261
+ }
262
+ }
263
+ catch (error) {
264
+ // Ignore permission errors
265
+ }
266
+ return files;
267
+ }
268
+ /**
269
+ * Parse HCL value (simplified)
270
+ */
271
+ parseValue(value) {
272
+ value = value.trim();
273
+ if (value === 'true')
274
+ return true;
275
+ if (value === 'false')
276
+ return false;
277
+ if (value.startsWith('"') && value.endsWith('"')) {
278
+ return value.slice(1, -1);
279
+ }
280
+ if (value.match(/^\d+$/)) {
281
+ return parseInt(value, 10);
282
+ }
283
+ return value;
284
+ }
285
+ /**
286
+ * Simple YAML parser (in production, use proper YAML library)
287
+ */
288
+ parseYAML(content) {
289
+ try {
290
+ return JSON.parse(content);
291
+ }
292
+ catch {
293
+ return {};
294
+ }
295
+ }
296
+ /**
297
+ * Get resource data for rule checking
298
+ */
299
+ getResourceData(resource, provider) {
300
+ if (provider === 'terraform') {
301
+ return resource.config;
302
+ }
303
+ else if (provider === 'kubernetes') {
304
+ return resource;
305
+ }
306
+ else if (provider === 'cloudformation') {
307
+ return resource.properties;
308
+ }
309
+ return {};
310
+ }
311
+ /**
312
+ * Get resource type
313
+ */
314
+ getResourceType(resource, provider) {
315
+ if (provider === 'terraform') {
316
+ return resource.type;
317
+ }
318
+ else if (provider === 'kubernetes') {
319
+ return resource.kind;
320
+ }
321
+ else if (provider === 'cloudformation') {
322
+ return resource.type;
323
+ }
324
+ return 'unknown';
325
+ }
326
+ /**
327
+ * Get resource name
328
+ */
329
+ getResourceName(resource, provider) {
330
+ if (provider === 'terraform') {
331
+ return resource.name;
332
+ }
333
+ else if (provider === 'kubernetes') {
334
+ return resource.metadata.name;
335
+ }
336
+ else if (provider === 'cloudformation') {
337
+ return resource.logicalId;
338
+ }
339
+ return 'unknown';
340
+ }
341
+ }
342
+ exports.IaCSecurityScanner = IaCSecurityScanner;
343
+ exports.iacSecurityScanner = new IaCSecurityScanner();
@@ -0,0 +1,7 @@
1
+ export * from './iac';
2
+ export * from './frameworks';
3
+ export * from './pii';
4
+ export * from './container';
5
+ export * from './automation';
6
+ export * from './audit';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,OAAO,CAAC;AAGtB,cAAc,cAAc,CAAC;AAG7B,cAAc,OAAO,CAAC;AAGtB,cAAc,aAAa,CAAC;AAG5B,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // IaC Security
18
+ __exportStar(require("./iac"), exports);
19
+ // Compliance Frameworks
20
+ __exportStar(require("./frameworks"), exports);
21
+ // PII Detection
22
+ __exportStar(require("./pii"), exports);
23
+ // Container Security
24
+ __exportStar(require("./container"), exports);
25
+ // Automation Components
26
+ __exportStar(require("./automation"), exports);
27
+ // Audit Trail (Compliance+ feature)
28
+ __exportStar(require("./audit"), exports);
@@ -0,0 +1,58 @@
1
+ export interface PIIFinding {
2
+ category: string;
3
+ value: string;
4
+ location: {
5
+ file: string;
6
+ line: number;
7
+ column: number;
8
+ };
9
+ context: string;
10
+ severity: 'high' | 'medium' | 'low';
11
+ }
12
+ export interface Origin {
13
+ type: 'input' | 'database' | 'api' | 'file' | 'environment';
14
+ location: string;
15
+ description: string;
16
+ }
17
+ export interface FlowPath {
18
+ from: string;
19
+ to: string;
20
+ operation: string;
21
+ line: number;
22
+ }
23
+ export interface Storage {
24
+ type: 'database' | 'file' | 'memory' | 'cache' | 'external';
25
+ location: string;
26
+ encrypted: boolean;
27
+ }
28
+ export interface DataFlow {
29
+ piiCategory: string;
30
+ origins: Origin[];
31
+ paths: FlowPath[];
32
+ storage: Storage[];
33
+ externalTransfers: string[];
34
+ }
35
+ export declare class DataFlowTracker {
36
+ /**
37
+ * Track where PII originates
38
+ */
39
+ trackOrigin(_finding: PIIFinding, _ast: any): Origin[];
40
+ /**
41
+ * Track where PII flows through the codebase
42
+ */
43
+ trackFlow(_finding: PIIFinding, _ast: any): FlowPath[];
44
+ /**
45
+ * Track where PII is stored
46
+ */
47
+ trackStorage(_finding: PIIFinding, _ast: any): Storage[];
48
+ /**
49
+ * Generate Mermaid diagram for data flows
50
+ */
51
+ generateDiagram(flows: DataFlow[]): string;
52
+ /**
53
+ * Analyze data flows for a project
54
+ */
55
+ analyzeDataFlows(findings: PIIFinding[]): DataFlow[];
56
+ }
57
+ export declare const dataFlowTracker: DataFlowTracker;
58
+ //# sourceMappingURL=data-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-flow.d.ts","sourceRoot":"","sources":["../../src/pii/data-flow.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACrC;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,aAAa,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,qBAAa,eAAe;IAC1B;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM,EAAE;IAoDtD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,GAAG,QAAQ,EAAE;IAStD;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,EAAE;IAiCxD;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM;IA6B1C;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE;CAmCrD;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dataFlowTracker = exports.DataFlowTracker = void 0;
4
+ class DataFlowTracker {
5
+ /**
6
+ * Track where PII originates
7
+ */
8
+ trackOrigin(_finding, _ast) {
9
+ const origins = [];
10
+ // Simplified - in production would analyze AST deeply
11
+ // Check if in request handler
12
+ if (_finding.context.includes('req.body') || _finding.context.includes('request')) {
13
+ origins.push({
14
+ type: 'input',
15
+ location: _finding.location.file,
16
+ description: 'User input from HTTP request'
17
+ });
18
+ }
19
+ // Check if from database query
20
+ if (_finding.context.includes('db.') || _finding.context.includes('query') || _finding.context.includes('findMany')) {
21
+ origins.push({
22
+ type: 'database',
23
+ location: _finding.location.file,
24
+ description: 'Retrieved from database'
25
+ });
26
+ }
27
+ // Check if from API call
28
+ if (_finding.context.includes('fetch') || _finding.context.includes('axios') || _finding.context.includes('http.get')) {
29
+ origins.push({
30
+ type: 'api',
31
+ location: _finding.location.file,
32
+ description: 'Fetched from external API'
33
+ });
34
+ }
35
+ // Check if from file
36
+ if (_finding.context.includes('readFile') || _finding.context.includes('fs.')) {
37
+ origins.push({
38
+ type: 'file',
39
+ location: _finding.location.file,
40
+ description: 'Read from file system'
41
+ });
42
+ }
43
+ // Check if from environment
44
+ if (_finding.context.includes('process.env') || _finding.context.includes('env.')) {
45
+ origins.push({
46
+ type: 'environment',
47
+ location: 'Environment variables',
48
+ description: 'Loaded from environment variables'
49
+ });
50
+ }
51
+ return origins;
52
+ }
53
+ /**
54
+ * Track where PII flows through the codebase
55
+ */
56
+ trackFlow(_finding, _ast) {
57
+ const paths = [];
58
+ // Simplified - would analyze actual data flow in AST
59
+ // This is a placeholder implementation
60
+ return paths;
61
+ }
62
+ /**
63
+ * Track where PII is stored
64
+ */
65
+ trackStorage(_finding, _ast) {
66
+ const storage = [];
67
+ // Check for database storage
68
+ if (_finding.context.includes('save') || _finding.context.includes('insert') || _finding.context.includes('create')) {
69
+ storage.push({
70
+ type: 'database',
71
+ location: 'Database (inferred)',
72
+ encrypted: false // Would check encryption settings
73
+ });
74
+ }
75
+ // Check for file storage
76
+ if (_finding.context.includes('writeFile') || _finding.context.includes('fs.write')) {
77
+ storage.push({
78
+ type: 'file',
79
+ location: _finding.location.file,
80
+ encrypted: false
81
+ });
82
+ }
83
+ // Check for cache storage
84
+ if (_finding.context.includes('cache') || _finding.context.includes('redis')) {
85
+ storage.push({
86
+ type: 'cache',
87
+ location: 'Cache (inferred)',
88
+ encrypted: false
89
+ });
90
+ }
91
+ return storage;
92
+ }
93
+ /**
94
+ * Generate Mermaid diagram for data flows
95
+ */
96
+ generateDiagram(flows) {
97
+ let diagram = 'graph LR\n';
98
+ for (const flow of flows) {
99
+ const piiNode = `PII_${flow.piiCategory.replace(/[^a-zA-Z0-9]/g, '_')}`;
100
+ // Origins
101
+ for (const origin of flow.origins) {
102
+ const originNode = `${origin.type}_${flow.piiCategory}`;
103
+ diagram += ` ${originNode}[${origin.type}: ${origin.description}] --> ${piiNode}[${flow.piiCategory}]\n`;
104
+ }
105
+ // Storage
106
+ for (const store of flow.storage) {
107
+ const storeNode = `${store.type}_${flow.piiCategory}`;
108
+ const encrypted = store.encrypted ? '🔒' : '🔓';
109
+ diagram += ` ${piiNode} --> ${storeNode}[${encrypted} ${store.type}]\n`;
110
+ }
111
+ // External transfers
112
+ for (const transfer of flow.externalTransfers) {
113
+ const transferNode = `EXT_${transfer.replace(/[^a-zA-Z0-9]/g, '_')}`;
114
+ diagram += ` ${piiNode} --> ${transferNode}[External: ${transfer}]\n`;
115
+ }
116
+ }
117
+ return diagram;
118
+ }
119
+ /**
120
+ * Analyze data flows for a project
121
+ */
122
+ analyzeDataFlows(findings) {
123
+ const flowsByCategory = new Map();
124
+ for (const finding of findings) {
125
+ if (!flowsByCategory.has(finding.category)) {
126
+ flowsByCategory.set(finding.category, {
127
+ piiCategory: finding.category,
128
+ origins: [],
129
+ paths: [],
130
+ storage: [],
131
+ externalTransfers: []
132
+ });
133
+ }
134
+ const flow = flowsByCategory.get(finding.category);
135
+ // Track origins (simplified without AST)
136
+ const origins = this.trackOrigin(finding, null);
137
+ for (const origin of origins) {
138
+ if (!flow.origins.some(o => o.type === origin.type && o.location === origin.location)) {
139
+ flow.origins.push(origin);
140
+ }
141
+ }
142
+ // Track storage (simplified without AST)
143
+ const storage = this.trackStorage(finding, null);
144
+ for (const store of storage) {
145
+ if (!flow.storage.some(s => s.type === store.type && s.location === store.location)) {
146
+ flow.storage.push(store);
147
+ }
148
+ }
149
+ }
150
+ return Array.from(flowsByCategory.values());
151
+ }
152
+ }
153
+ exports.DataFlowTracker = DataFlowTracker;
154
+ exports.dataFlowTracker = new DataFlowTracker();
@@ -0,0 +1,60 @@
1
+ import { PIIFinding, DataFlow } from './data-flow';
2
+ export interface PIIDetectionResult {
3
+ projectId: string;
4
+ summary: {
5
+ totalFindings: number;
6
+ byCategory: Record<string, number>;
7
+ riskLevel: 'high' | 'medium' | 'low';
8
+ };
9
+ findings: PIIFinding[];
10
+ dataFlows: DataFlow[];
11
+ recommendations: string[];
12
+ }
13
+ export declare class PIIDetector {
14
+ /**
15
+ * Detect PII in entire project
16
+ */
17
+ detectPII(projectPath: string, projectId: string): Promise<PIIDetectionResult>;
18
+ /**
19
+ * Scan file content for PII patterns
20
+ */
21
+ private scanContent;
22
+ /**
23
+ * Scan AST for PII field names
24
+ */
25
+ private scanFieldNames;
26
+ /**
27
+ * Track data flows for PII
28
+ */
29
+ private trackPIIDataFlows;
30
+ /**
31
+ * Generate recommendations based on findings
32
+ */
33
+ private generateRecommendations;
34
+ /**
35
+ * Find source files in project
36
+ */
37
+ private findSourceFiles;
38
+ /**
39
+ * Check if value is a test value
40
+ */
41
+ private isTestValue;
42
+ /**
43
+ * Check if context indicates non-PII usage
44
+ */
45
+ private isNonPIIContext;
46
+ /**
47
+ * Get line and column from position
48
+ */
49
+ private getLineAndColumn;
50
+ /**
51
+ * Get context around a line
52
+ */
53
+ private getContext;
54
+ /**
55
+ * Mask sensitive value
56
+ */
57
+ private maskValue;
58
+ }
59
+ export declare const piiDetector: PIIDetector;
60
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/pii/detector.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;KACtC,CAAC;IACF,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,qBAAa,WAAW;IACtB;;OAEG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgEpF;;OAEG;IACH,OAAO,CAAC,WAAW;IA6CnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAyCtB;;OAEG;YACW,iBAAiB;IAK/B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA4C/B;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAMlB;;OAEG;IACH,OAAO,CAAC,SAAS;CAqBlB;AAED,eAAO,MAAM,WAAW,aAAoB,CAAC"}