tlc-claude-code 1.4.7 → 1.4.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.
Files changed (170) hide show
  1. package/docker-compose.dev.yml +6 -3
  2. package/package.json +1 -1
  3. package/server/index.js +229 -14
  4. package/server/lib/compliance/control-mapper.js +401 -0
  5. package/server/lib/compliance/control-mapper.test.js +117 -0
  6. package/server/lib/compliance/evidence-linker.js +296 -0
  7. package/server/lib/compliance/evidence-linker.test.js +121 -0
  8. package/server/lib/compliance/gdpr-checklist.js +416 -0
  9. package/server/lib/compliance/gdpr-checklist.test.js +131 -0
  10. package/server/lib/compliance/hipaa-checklist.js +277 -0
  11. package/server/lib/compliance/hipaa-checklist.test.js +101 -0
  12. package/server/lib/compliance/iso27001-checklist.js +287 -0
  13. package/server/lib/compliance/iso27001-checklist.test.js +99 -0
  14. package/server/lib/compliance/multi-framework-reporter.js +284 -0
  15. package/server/lib/compliance/multi-framework-reporter.test.js +127 -0
  16. package/server/lib/compliance/pci-dss-checklist.js +214 -0
  17. package/server/lib/compliance/pci-dss-checklist.test.js +95 -0
  18. package/server/lib/compliance/trust-centre.js +187 -0
  19. package/server/lib/compliance/trust-centre.test.js +93 -0
  20. package/server/lib/dashboard/api-server.js +155 -0
  21. package/server/lib/dashboard/api-server.test.js +155 -0
  22. package/server/lib/dashboard/health-api.js +199 -0
  23. package/server/lib/dashboard/health-api.test.js +122 -0
  24. package/server/lib/dashboard/notes-api.js +234 -0
  25. package/server/lib/dashboard/notes-api.test.js +134 -0
  26. package/server/lib/dashboard/router-api.js +176 -0
  27. package/server/lib/dashboard/router-api.test.js +132 -0
  28. package/server/lib/dashboard/tasks-api.js +289 -0
  29. package/server/lib/dashboard/tasks-api.test.js +161 -0
  30. package/server/lib/dashboard/tlc-introspection.js +197 -0
  31. package/server/lib/dashboard/tlc-introspection.test.js +138 -0
  32. package/server/lib/dashboard/version-api.js +222 -0
  33. package/server/lib/dashboard/version-api.test.js +112 -0
  34. package/server/lib/dashboard/websocket-server.js +104 -0
  35. package/server/lib/dashboard/websocket-server.test.js +118 -0
  36. package/server/lib/deploy/branch-classifier.js +163 -0
  37. package/server/lib/deploy/branch-classifier.test.js +164 -0
  38. package/server/lib/deploy/deployment-approval.js +299 -0
  39. package/server/lib/deploy/deployment-approval.test.js +296 -0
  40. package/server/lib/deploy/deployment-audit.js +374 -0
  41. package/server/lib/deploy/deployment-audit.test.js +307 -0
  42. package/server/lib/deploy/deployment-executor.js +335 -0
  43. package/server/lib/deploy/deployment-executor.test.js +329 -0
  44. package/server/lib/deploy/deployment-rules.js +163 -0
  45. package/server/lib/deploy/deployment-rules.test.js +188 -0
  46. package/server/lib/deploy/rollback-manager.js +379 -0
  47. package/server/lib/deploy/rollback-manager.test.js +321 -0
  48. package/server/lib/deploy/security-gates.js +236 -0
  49. package/server/lib/deploy/security-gates.test.js +222 -0
  50. package/server/lib/k8s/gitops-config.js +188 -0
  51. package/server/lib/k8s/gitops-config.test.js +59 -0
  52. package/server/lib/k8s/helm-generator.js +196 -0
  53. package/server/lib/k8s/helm-generator.test.js +59 -0
  54. package/server/lib/k8s/kustomize-generator.js +176 -0
  55. package/server/lib/k8s/kustomize-generator.test.js +58 -0
  56. package/server/lib/k8s/network-policy.js +114 -0
  57. package/server/lib/k8s/network-policy.test.js +53 -0
  58. package/server/lib/k8s/pod-security.js +114 -0
  59. package/server/lib/k8s/pod-security.test.js +55 -0
  60. package/server/lib/k8s/rbac-generator.js +132 -0
  61. package/server/lib/k8s/rbac-generator.test.js +57 -0
  62. package/server/lib/k8s/resource-manager.js +172 -0
  63. package/server/lib/k8s/resource-manager.test.js +60 -0
  64. package/server/lib/k8s/secrets-encryption.js +168 -0
  65. package/server/lib/k8s/secrets-encryption.test.js +49 -0
  66. package/server/lib/monitoring/alert-manager.js +238 -0
  67. package/server/lib/monitoring/alert-manager.test.js +106 -0
  68. package/server/lib/monitoring/health-check.js +226 -0
  69. package/server/lib/monitoring/health-check.test.js +176 -0
  70. package/server/lib/monitoring/incident-manager.js +230 -0
  71. package/server/lib/monitoring/incident-manager.test.js +98 -0
  72. package/server/lib/monitoring/log-aggregator.js +147 -0
  73. package/server/lib/monitoring/log-aggregator.test.js +89 -0
  74. package/server/lib/monitoring/metrics-collector.js +337 -0
  75. package/server/lib/monitoring/metrics-collector.test.js +172 -0
  76. package/server/lib/monitoring/status-page.js +214 -0
  77. package/server/lib/monitoring/status-page.test.js +105 -0
  78. package/server/lib/monitoring/uptime-monitor.js +194 -0
  79. package/server/lib/monitoring/uptime-monitor.test.js +109 -0
  80. package/server/lib/network/fail2ban-config.js +294 -0
  81. package/server/lib/network/fail2ban-config.test.js +275 -0
  82. package/server/lib/network/firewall-manager.js +252 -0
  83. package/server/lib/network/firewall-manager.test.js +254 -0
  84. package/server/lib/network/geoip-filter.js +282 -0
  85. package/server/lib/network/geoip-filter.test.js +264 -0
  86. package/server/lib/network/rate-limiter.js +229 -0
  87. package/server/lib/network/rate-limiter.test.js +293 -0
  88. package/server/lib/network/request-validator.js +351 -0
  89. package/server/lib/network/request-validator.test.js +345 -0
  90. package/server/lib/network/security-headers.js +251 -0
  91. package/server/lib/network/security-headers.test.js +283 -0
  92. package/server/lib/network/tls-config.js +210 -0
  93. package/server/lib/network/tls-config.test.js +248 -0
  94. package/server/lib/security/auth-security.js +369 -0
  95. package/server/lib/security/auth-security.test.js +448 -0
  96. package/server/lib/security/cis-benchmark.js +152 -0
  97. package/server/lib/security/cis-benchmark.test.js +137 -0
  98. package/server/lib/security/compose-templates.js +312 -0
  99. package/server/lib/security/compose-templates.test.js +229 -0
  100. package/server/lib/security/container-runtime.js +456 -0
  101. package/server/lib/security/container-runtime.test.js +503 -0
  102. package/server/lib/security/cors-validator.js +278 -0
  103. package/server/lib/security/cors-validator.test.js +310 -0
  104. package/server/lib/security/crypto-utils.js +253 -0
  105. package/server/lib/security/crypto-utils.test.js +409 -0
  106. package/server/lib/security/dockerfile-linter.js +459 -0
  107. package/server/lib/security/dockerfile-linter.test.js +483 -0
  108. package/server/lib/security/dockerfile-templates.js +278 -0
  109. package/server/lib/security/dockerfile-templates.test.js +164 -0
  110. package/server/lib/security/error-sanitizer.js +426 -0
  111. package/server/lib/security/error-sanitizer.test.js +331 -0
  112. package/server/lib/security/headers-generator.js +368 -0
  113. package/server/lib/security/headers-generator.test.js +398 -0
  114. package/server/lib/security/image-scanner.js +83 -0
  115. package/server/lib/security/image-scanner.test.js +106 -0
  116. package/server/lib/security/input-validator.js +352 -0
  117. package/server/lib/security/input-validator.test.js +330 -0
  118. package/server/lib/security/network-policy.js +174 -0
  119. package/server/lib/security/network-policy.test.js +164 -0
  120. package/server/lib/security/output-encoder.js +237 -0
  121. package/server/lib/security/output-encoder.test.js +276 -0
  122. package/server/lib/security/path-validator.js +359 -0
  123. package/server/lib/security/path-validator.test.js +293 -0
  124. package/server/lib/security/query-builder.js +421 -0
  125. package/server/lib/security/query-builder.test.js +318 -0
  126. package/server/lib/security/secret-detector.js +290 -0
  127. package/server/lib/security/secret-detector.test.js +354 -0
  128. package/server/lib/security/secrets-validator.js +137 -0
  129. package/server/lib/security/secrets-validator.test.js +120 -0
  130. package/server/lib/security-testing/dast-runner.js +154 -0
  131. package/server/lib/security-testing/dast-runner.test.js +62 -0
  132. package/server/lib/security-testing/dependency-scanner.js +172 -0
  133. package/server/lib/security-testing/dependency-scanner.test.js +64 -0
  134. package/server/lib/security-testing/pentest-runner.js +230 -0
  135. package/server/lib/security-testing/pentest-runner.test.js +60 -0
  136. package/server/lib/security-testing/sast-runner.js +136 -0
  137. package/server/lib/security-testing/sast-runner.test.js +62 -0
  138. package/server/lib/security-testing/secret-scanner.js +153 -0
  139. package/server/lib/security-testing/secret-scanner.test.js +66 -0
  140. package/server/lib/security-testing/security-gate.js +216 -0
  141. package/server/lib/security-testing/security-gate.test.js +115 -0
  142. package/server/lib/security-testing/security-reporter.js +303 -0
  143. package/server/lib/security-testing/security-reporter.test.js +114 -0
  144. package/server/lib/standards/audit-checker.js +546 -0
  145. package/server/lib/standards/audit-checker.test.js +415 -0
  146. package/server/lib/standards/cleanup-executor.js +452 -0
  147. package/server/lib/standards/cleanup-executor.test.js +293 -0
  148. package/server/lib/standards/refactor-stepper.js +425 -0
  149. package/server/lib/standards/refactor-stepper.test.js +298 -0
  150. package/server/lib/standards/standards-injector.js +167 -0
  151. package/server/lib/standards/standards-injector.test.js +232 -0
  152. package/server/lib/user-management.test.js +284 -0
  153. package/server/lib/vps/backup-manager.js +157 -0
  154. package/server/lib/vps/backup-manager.test.js +59 -0
  155. package/server/lib/vps/caddy-config.js +159 -0
  156. package/server/lib/vps/caddy-config.test.js +48 -0
  157. package/server/lib/vps/compose-orchestrator.js +219 -0
  158. package/server/lib/vps/compose-orchestrator.test.js +50 -0
  159. package/server/lib/vps/database-config.js +208 -0
  160. package/server/lib/vps/database-config.test.js +47 -0
  161. package/server/lib/vps/deploy-script.js +211 -0
  162. package/server/lib/vps/deploy-script.test.js +53 -0
  163. package/server/lib/vps/secrets-manager.js +148 -0
  164. package/server/lib/vps/secrets-manager.test.js +58 -0
  165. package/server/lib/vps/server-hardening.js +174 -0
  166. package/server/lib/vps/server-hardening.test.js +70 -0
  167. package/server/package-lock.json +19 -0
  168. package/server/package.json +1 -0
  169. package/server/templates/CLAUDE.md +37 -0
  170. package/server/templates/CODING-STANDARDS.md +408 -0
@@ -0,0 +1,154 @@
1
+ /**
2
+ * DAST Runner - OWASP ZAP Dynamic Application Security Testing
3
+ */
4
+
5
+ /**
6
+ * Run ZAP baseline scan
7
+ * @param {Object} options - Scan options
8
+ * @param {string} options.target - Target URL to scan
9
+ * @param {Function} options.exec - Exec function for running commands
10
+ * @returns {Promise<Object>} Scan results
11
+ */
12
+ export async function runZapBaseline({ target, exec }) {
13
+ const command = `zap-baseline.py -t ${target} -J report.json`;
14
+ const { stdout } = await exec(command);
15
+ return JSON.parse(stdout);
16
+ }
17
+
18
+ /**
19
+ * Run ZAP full scan
20
+ * @param {Object} options - Scan options
21
+ * @param {string} options.target - Target URL to scan
22
+ * @param {Function} options.exec - Exec function for running commands
23
+ * @returns {Promise<Object>} Scan results
24
+ */
25
+ export async function runZapFullScan({ target, exec }) {
26
+ const command = `zap-full-scan.py -t ${target} -J report.json`;
27
+ const { stdout } = await exec(command);
28
+ return JSON.parse(stdout);
29
+ }
30
+
31
+ /**
32
+ * Parse ZAP JSON report into normalized alerts
33
+ * @param {Object} report - Raw ZAP report
34
+ * @returns {Array} Normalized alerts
35
+ */
36
+ export function parseZapReport(report) {
37
+ const alerts = [];
38
+ const riskMap = { '0': 'info', '1': 'low', '2': 'medium', '3': 'high' };
39
+
40
+ for (const site of report.site || []) {
41
+ for (const alert of site.alerts || []) {
42
+ alerts.push({
43
+ name: alert.alert,
44
+ risk: riskMap[alert.riskcode] || 'info',
45
+ description: alert.desc || alert.description || '',
46
+ instances: alert.instances || []
47
+ });
48
+ }
49
+ }
50
+
51
+ return alerts;
52
+ }
53
+
54
+ /**
55
+ * Configure scan policy
56
+ * @param {Object} options - Policy options
57
+ * @param {string} options.strength - Scan strength (low, medium, high)
58
+ * @param {string} options.threshold - Alert threshold
59
+ * @returns {Object} Configured policy
60
+ */
61
+ export function configureScanPolicy(options = {}) {
62
+ return {
63
+ strength: options.strength || 'medium',
64
+ threshold: options.threshold || 'medium',
65
+ maxDuration: options.maxDuration || 60,
66
+ maxDepth: options.maxDepth || 5
67
+ };
68
+ }
69
+
70
+ /**
71
+ * Generate HTML report from alerts
72
+ * @param {Array} alerts - List of alerts
73
+ * @returns {string} HTML report
74
+ */
75
+ export function generateHtmlReport(alerts) {
76
+ let html = `<!DOCTYPE html>
77
+ <html>
78
+ <head>
79
+ <title>DAST Scan Report</title>
80
+ <style>
81
+ body { font-family: Arial, sans-serif; margin: 20px; }
82
+ .alert { margin: 10px 0; padding: 10px; border: 1px solid #ccc; }
83
+ .high { border-color: red; background: #ffe0e0; }
84
+ .medium { border-color: orange; background: #fff3e0; }
85
+ .low { border-color: yellow; background: #fffde0; }
86
+ .info { border-color: blue; background: #e0f0ff; }
87
+ </style>
88
+ </head>
89
+ <body>
90
+ <h1>DAST Scan Report</h1>
91
+ <p>Found ${alerts.length} alert(s)</p>
92
+ `;
93
+
94
+ for (const alert of alerts) {
95
+ html += ` <div class="alert ${alert.risk}">
96
+ <h3>${alert.name}</h3>
97
+ <p><strong>Risk:</strong> ${alert.risk}</p>
98
+ <p>${alert.description}</p>
99
+ </div>
100
+ `;
101
+ }
102
+
103
+ html += `</body>
104
+ </html>`;
105
+
106
+ return html;
107
+ }
108
+
109
+ /**
110
+ * Create a DAST runner instance
111
+ * @param {Object} options - Runner options
112
+ * @returns {Object} DAST runner instance
113
+ */
114
+ export function createDastRunner(options = {}) {
115
+ return {
116
+ /**
117
+ * Run baseline scan
118
+ * @param {Object} scanOptions - Scan options
119
+ * @returns {Promise<Object>} Scan results
120
+ */
121
+ async baseline(scanOptions) {
122
+ const { target, auth, mockResults, exec } = scanOptions;
123
+
124
+ if (mockResults !== undefined) {
125
+ return mockResults;
126
+ }
127
+
128
+ if (exec) {
129
+ return await runZapBaseline({ target, exec });
130
+ }
131
+
132
+ return { alerts: [] };
133
+ },
134
+
135
+ /**
136
+ * Run full scan
137
+ * @param {Object} scanOptions - Scan options
138
+ * @returns {Promise<Object>} Scan results
139
+ */
140
+ async fullScan(scanOptions) {
141
+ const { target, auth, mockResults, exec } = scanOptions;
142
+
143
+ if (mockResults !== undefined) {
144
+ return mockResults;
145
+ }
146
+
147
+ if (exec) {
148
+ return await runZapFullScan({ target, exec });
149
+ }
150
+
151
+ return { alerts: [] };
152
+ }
153
+ };
154
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * DAST Runner Tests
3
+ */
4
+ import { describe, it, expect, vi } from 'vitest';
5
+ import { runZapBaseline, runZapFullScan, parseZapReport, configureScanPolicy, generateHtmlReport, createDastRunner } from './dast-runner.js';
6
+
7
+ describe('dast-runner', () => {
8
+ describe('runZapBaseline', () => {
9
+ it('runs ZAP baseline scan', async () => {
10
+ const mockExec = vi.fn().mockResolvedValue({ stdout: '{"alerts": []}' });
11
+ const result = await runZapBaseline({ target: 'http://localhost:3000', exec: mockExec });
12
+ expect(result.alerts).toBeDefined();
13
+ });
14
+ });
15
+
16
+ describe('runZapFullScan', () => {
17
+ it('runs ZAP full scan', async () => {
18
+ const mockExec = vi.fn().mockResolvedValue({ stdout: '{"alerts": []}' });
19
+ const result = await runZapFullScan({ target: 'http://localhost:3000', exec: mockExec });
20
+ expect(result).toBeDefined();
21
+ });
22
+ });
23
+
24
+ describe('parseZapReport', () => {
25
+ it('parses ZAP JSON report', () => {
26
+ const report = { site: [{ alerts: [{ alert: 'XSS', riskcode: '3', instances: [{ uri: '/test' }] }] }] };
27
+ const parsed = parseZapReport(report);
28
+ expect(parsed[0].name).toBe('XSS');
29
+ expect(parsed[0].risk).toBe('high');
30
+ });
31
+ });
32
+
33
+ describe('configureScanPolicy', () => {
34
+ it('configures scan policy', () => {
35
+ const policy = configureScanPolicy({ strength: 'high', threshold: 'medium' });
36
+ expect(policy.strength).toBe('high');
37
+ });
38
+ });
39
+
40
+ describe('generateHtmlReport', () => {
41
+ it('generates HTML report', () => {
42
+ const alerts = [{ name: 'XSS', risk: 'high', description: 'Cross-site scripting' }];
43
+ const html = generateHtmlReport(alerts);
44
+ expect(html).toContain('<html');
45
+ expect(html).toContain('XSS');
46
+ });
47
+ });
48
+
49
+ describe('createDastRunner', () => {
50
+ it('creates runner', () => {
51
+ const runner = createDastRunner();
52
+ expect(runner.baseline).toBeDefined();
53
+ expect(runner.fullScan).toBeDefined();
54
+ });
55
+
56
+ it('supports authenticated scanning', async () => {
57
+ const runner = createDastRunner();
58
+ const result = await runner.baseline({ target: 'http://localhost', auth: { username: 'test', password: 'test' }, mockResults: { alerts: [] } });
59
+ expect(result).toBeDefined();
60
+ });
61
+ });
62
+ });
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Dependency Scanner - npm audit and Trivy scanning
3
+ */
4
+
5
+ /**
6
+ * Run npm audit
7
+ * @param {Object} options - Scan options
8
+ * @param {Function} options.exec - Exec function for running commands
9
+ * @returns {Promise<Object>} Audit results
10
+ */
11
+ export async function runNpmAudit({ exec }) {
12
+ const command = 'npm audit --json';
13
+ const { stdout } = await exec(command);
14
+ return JSON.parse(stdout);
15
+ }
16
+
17
+ /**
18
+ * Run Trivy scan
19
+ * @param {Object} options - Scan options
20
+ * @param {string} options.path - Path to scan
21
+ * @param {Function} options.exec - Exec function for running commands
22
+ * @returns {Promise<Object>} Scan results
23
+ */
24
+ export async function runTrivyScan({ path, exec }) {
25
+ const command = `trivy fs --format json ${path}`;
26
+ const { stdout } = await exec(command);
27
+ return JSON.parse(stdout);
28
+ }
29
+
30
+ /**
31
+ * Parse vulnerability results into normalized format
32
+ * @param {Object} results - Raw audit results
33
+ * @returns {Array} Normalized vulnerabilities
34
+ */
35
+ export function parseVulnerabilities(results) {
36
+ const vulnerabilities = [];
37
+
38
+ if (results.vulnerabilities) {
39
+ for (const [pkg, vuln] of Object.entries(results.vulnerabilities)) {
40
+ const title = vuln.via?.[0]?.title || vuln.via?.[0] || 'Unknown vulnerability';
41
+ vulnerabilities.push({
42
+ package: pkg,
43
+ severity: vuln.severity,
44
+ title: typeof title === 'string' ? title : title.title || 'Unknown',
45
+ fixAvailable: vuln.fixAvailable || false
46
+ });
47
+ }
48
+ }
49
+
50
+ return vulnerabilities;
51
+ }
52
+
53
+ /**
54
+ * Check license compliance
55
+ * @param {Array} deps - List of dependencies with licenses
56
+ * @param {Object} options - License policy options
57
+ * @param {Array} options.allowed - List of allowed licenses
58
+ * @returns {Object} Compliance result
59
+ */
60
+ export function checkLicenses(deps, options = {}) {
61
+ const { allowed = [] } = options;
62
+ const violations = [];
63
+
64
+ for (const dep of deps) {
65
+ if (!allowed.includes(dep.license)) {
66
+ violations.push({
67
+ package: dep.name,
68
+ license: dep.license
69
+ });
70
+ }
71
+ }
72
+
73
+ return {
74
+ compliant: violations.length === 0,
75
+ violations
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Generate Software Bill of Materials (SBOM)
81
+ * @param {Array} deps - List of dependencies
82
+ * @param {Object} options - SBOM options
83
+ * @param {string} options.format - Output format (cyclonedx, spdx)
84
+ * @returns {string} SBOM in specified format
85
+ */
86
+ export function generateSbom(deps, options = {}) {
87
+ const { format = 'cyclonedx' } = options;
88
+
89
+ if (format === 'cyclonedx') {
90
+ const sbom = {
91
+ bomFormat: 'CycloneDX',
92
+ specVersion: '1.4',
93
+ version: 1,
94
+ components: deps.map(dep => ({
95
+ type: 'library',
96
+ name: dep.name,
97
+ version: dep.version
98
+ }))
99
+ };
100
+ return JSON.stringify(sbom, null, 2);
101
+ }
102
+
103
+ // SPDX format
104
+ const sbom = {
105
+ spdxVersion: 'SPDX-2.3',
106
+ packages: deps.map(dep => ({
107
+ name: dep.name,
108
+ version: dep.version
109
+ }))
110
+ };
111
+ return JSON.stringify(sbom, null, 2);
112
+ }
113
+
114
+ /**
115
+ * Create a dependency scanner instance
116
+ * @param {Object} options - Scanner options
117
+ * @returns {Object} Dependency scanner instance
118
+ */
119
+ export function createDependencyScanner(options = {}) {
120
+ return {
121
+ /**
122
+ * Run dependency scan
123
+ * @param {Object} scanOptions - Scan options
124
+ * @returns {Promise<Array>} Vulnerability results
125
+ */
126
+ async scan(scanOptions) {
127
+ const { severity, mockResults, exec } = scanOptions;
128
+
129
+ let results;
130
+ if (mockResults !== undefined) {
131
+ results = mockResults;
132
+ } else if (exec) {
133
+ const auditResults = await runNpmAudit({ exec });
134
+ results = parseVulnerabilities(auditResults);
135
+ } else {
136
+ results = [];
137
+ }
138
+
139
+ // Filter by severity if specified
140
+ if (severity) {
141
+ const severityOrder = ['low', 'moderate', 'high', 'critical'];
142
+ const minIndex = severityOrder.indexOf(severity.toLowerCase());
143
+ results = results.filter(r => {
144
+ const rIndex = severityOrder.indexOf(r.severity?.toLowerCase());
145
+ return rIndex >= minIndex;
146
+ });
147
+ }
148
+
149
+ return results;
150
+ },
151
+
152
+ /**
153
+ * Check license compliance
154
+ * @param {Array} deps - Dependencies to check
155
+ * @param {Object} policy - License policy
156
+ * @returns {Object} Compliance result
157
+ */
158
+ checkLicenses(deps, policy) {
159
+ return checkLicenses(deps, policy);
160
+ },
161
+
162
+ /**
163
+ * Generate SBOM
164
+ * @param {Array} deps - Dependencies
165
+ * @param {Object} sbomOptions - SBOM options
166
+ * @returns {string} SBOM output
167
+ */
168
+ generateSbom(deps, sbomOptions) {
169
+ return generateSbom(deps, sbomOptions);
170
+ }
171
+ };
172
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Dependency Scanner Tests
3
+ */
4
+ import { describe, it, expect, vi } from 'vitest';
5
+ import { runNpmAudit, runTrivyScan, parseVulnerabilities, checkLicenses, generateSbom, createDependencyScanner } from './dependency-scanner.js';
6
+
7
+ describe('dependency-scanner', () => {
8
+ describe('runNpmAudit', () => {
9
+ it('runs npm audit', async () => {
10
+ const mockExec = vi.fn().mockResolvedValue({ stdout: '{"vulnerabilities": {}}' });
11
+ const result = await runNpmAudit({ exec: mockExec });
12
+ expect(result.vulnerabilities).toBeDefined();
13
+ });
14
+ });
15
+
16
+ describe('runTrivyScan', () => {
17
+ it('runs Trivy scan', async () => {
18
+ const mockExec = vi.fn().mockResolvedValue({ stdout: '{"Results": []}' });
19
+ const result = await runTrivyScan({ path: '.', exec: mockExec });
20
+ expect(result.Results).toBeDefined();
21
+ });
22
+ });
23
+
24
+ describe('parseVulnerabilities', () => {
25
+ it('parses vulnerability results', () => {
26
+ const results = { vulnerabilities: { lodash: { severity: 'high', via: [{ title: 'Prototype Pollution' }] } } };
27
+ const parsed = parseVulnerabilities(results);
28
+ expect(parsed[0].package).toBe('lodash');
29
+ expect(parsed[0].severity).toBe('high');
30
+ });
31
+ });
32
+
33
+ describe('checkLicenses', () => {
34
+ it('checks license compliance', () => {
35
+ const deps = [{ name: 'pkg1', license: 'MIT' }, { name: 'pkg2', license: 'GPL-3.0' }];
36
+ const result = checkLicenses(deps, { allowed: ['MIT', 'Apache-2.0'] });
37
+ expect(result.compliant).toBe(false);
38
+ expect(result.violations[0].package).toBe('pkg2');
39
+ });
40
+ });
41
+
42
+ describe('generateSbom', () => {
43
+ it('generates SBOM', () => {
44
+ const deps = [{ name: 'lodash', version: '4.17.21' }];
45
+ const sbom = generateSbom(deps, { format: 'cyclonedx' });
46
+ expect(sbom).toContain('bomFormat');
47
+ });
48
+ });
49
+
50
+ describe('createDependencyScanner', () => {
51
+ it('creates scanner', () => {
52
+ const scanner = createDependencyScanner();
53
+ expect(scanner.scan).toBeDefined();
54
+ expect(scanner.checkLicenses).toBeDefined();
55
+ expect(scanner.generateSbom).toBeDefined();
56
+ });
57
+
58
+ it('filters by severity threshold', async () => {
59
+ const scanner = createDependencyScanner();
60
+ const results = await scanner.scan({ severity: 'high', mockResults: [{ severity: 'high' }, { severity: 'low' }] });
61
+ expect(results.every(r => r.severity === 'high')).toBe(true);
62
+ });
63
+ });
64
+ });
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Pentest Runner - Nuclei penetration testing
3
+ */
4
+
5
+ // Common SQL injection payloads
6
+ const SQL_PAYLOADS = [
7
+ "' OR '1'='1",
8
+ "1; DROP TABLE users--",
9
+ "' UNION SELECT * FROM users--",
10
+ "1' AND '1'='1"
11
+ ];
12
+
13
+ // Common XSS payloads
14
+ const XSS_PAYLOADS = [
15
+ '<script>alert(1)</script>',
16
+ '<img src=x onerror=alert(1)>',
17
+ '"><script>alert(1)</script>',
18
+ "javascript:alert(1)"
19
+ ];
20
+
21
+ /**
22
+ * Run Nuclei scan
23
+ * @param {Object} options - Scan options
24
+ * @param {string} options.target - Target URL
25
+ * @param {Array} options.templates - Template categories to use
26
+ * @param {Function} options.exec - Exec function for running commands
27
+ * @returns {Promise<Array>} Scan findings
28
+ */
29
+ export async function runNuclei({ target, templates = [], exec }) {
30
+ let command = `nuclei -u ${target} -json`;
31
+
32
+ if (templates.length > 0) {
33
+ command += ` -t ${templates.join(',')}`;
34
+ }
35
+
36
+ const { stdout } = await exec(command);
37
+ return JSON.parse(stdout);
38
+ }
39
+
40
+ /**
41
+ * Test for SQL injection vulnerabilities
42
+ * @param {Object} options - Test options
43
+ * @param {string} options.url - URL to test
44
+ * @param {Function} options.mockFetch - Mock fetch function for testing
45
+ * @returns {Promise<Object>} Test result
46
+ */
47
+ export async function testSqlInjection({ url, mockFetch }) {
48
+ const fetchFn = mockFetch || fetch;
49
+
50
+ for (const payload of SQL_PAYLOADS) {
51
+ try {
52
+ const testUrl = `${url}?id=${encodeURIComponent(payload)}`;
53
+ const response = await fetchFn(testUrl);
54
+ const text = await response.text();
55
+
56
+ // Check for SQL error messages indicating vulnerability
57
+ const errorPatterns = [
58
+ 'error in your SQL syntax',
59
+ 'mysql_fetch',
60
+ 'ORA-',
61
+ 'SQLServer',
62
+ 'sqlite3',
63
+ 'PostgreSQL',
64
+ 'SQLSTATE'
65
+ ];
66
+
67
+ if (errorPatterns.some(pattern => text.toLowerCase().includes(pattern.toLowerCase()))) {
68
+ return {
69
+ vulnerable: true,
70
+ payload,
71
+ evidence: text.substring(0, 200)
72
+ };
73
+ }
74
+ } catch (e) {
75
+ // Continue testing
76
+ }
77
+ }
78
+
79
+ return { vulnerable: false };
80
+ }
81
+
82
+ /**
83
+ * Test for XSS vulnerabilities
84
+ * @param {Object} options - Test options
85
+ * @param {string} options.url - URL to test
86
+ * @param {Function} options.mockFetch - Mock fetch function for testing
87
+ * @returns {Promise<Object>} Test result
88
+ */
89
+ export async function testXss({ url, mockFetch }) {
90
+ const fetchFn = mockFetch || fetch;
91
+
92
+ for (const payload of XSS_PAYLOADS) {
93
+ try {
94
+ const testUrl = `${url}?q=${encodeURIComponent(payload)}`;
95
+ const response = await fetchFn(testUrl);
96
+ const text = await response.text();
97
+
98
+ // Check if payload is reflected without encoding
99
+ if (text.includes(payload)) {
100
+ return {
101
+ vulnerable: true,
102
+ payload,
103
+ evidence: text.substring(0, 200)
104
+ };
105
+ }
106
+ } catch (e) {
107
+ // Continue testing
108
+ }
109
+ }
110
+
111
+ return { vulnerable: false };
112
+ }
113
+
114
+ /**
115
+ * Test for authentication bypass
116
+ * @param {Object} options - Test options
117
+ * @param {string} options.url - Protected URL to test
118
+ * @param {Function} options.mockFetch - Mock fetch function for testing
119
+ * @returns {Promise<Object>} Test result
120
+ */
121
+ export async function testAuthBypass({ url, mockFetch }) {
122
+ const fetchFn = mockFetch || fetch;
123
+
124
+ try {
125
+ // Test accessing protected resource without authentication
126
+ const response = await fetchFn(url, {
127
+ headers: {
128
+ // No auth headers
129
+ }
130
+ });
131
+
132
+ // If we get a 200 on a protected endpoint, it's likely vulnerable
133
+ if (response.status === 200) {
134
+ return {
135
+ vulnerable: true,
136
+ evidence: 'Protected endpoint accessible without authentication'
137
+ };
138
+ }
139
+ } catch (e) {
140
+ // Network error, not a vulnerability indicator
141
+ }
142
+
143
+ return { vulnerable: false };
144
+ }
145
+
146
+ /**
147
+ * Generate penetration test report
148
+ * @param {Array} findings - List of findings
149
+ * @returns {string} Formatted report
150
+ */
151
+ export function generatePentestReport(findings) {
152
+ if (findings.length === 0) {
153
+ return '# Penetration Test Report\n\nNo vulnerabilities found.';
154
+ }
155
+
156
+ let report = '# Penetration Test Report\n\n';
157
+ report += `Found ${findings.length} vulnerability(ies):\n\n`;
158
+
159
+ const typeLabels = {
160
+ sqli: 'SQL Injection',
161
+ xss: 'Cross-Site Scripting (XSS)',
162
+ auth_bypass: 'Authentication Bypass',
163
+ default: 'Security Issue'
164
+ };
165
+
166
+ for (const finding of findings) {
167
+ const label = typeLabels[finding.type] || typeLabels.default;
168
+ report += `## ${label}\n`;
169
+ report += `- **Severity:** ${finding.severity}\n`;
170
+ report += `- **URL:** ${finding.url}\n`;
171
+ if (finding.payload) {
172
+ report += `- **Payload:** ${finding.payload}\n`;
173
+ }
174
+ if (finding.evidence) {
175
+ report += `- **Evidence:** ${finding.evidence}\n`;
176
+ }
177
+ report += '\n';
178
+ }
179
+
180
+ return report;
181
+ }
182
+
183
+ /**
184
+ * Create a pentest runner instance
185
+ * @param {Object} options - Runner options
186
+ * @returns {Object} Pentest runner instance
187
+ */
188
+ export function createPentestRunner(options = {}) {
189
+ return {
190
+ /**
191
+ * Run full scan with Nuclei
192
+ * @param {Object} scanOptions - Scan options
193
+ * @returns {Promise<Array>} Scan findings
194
+ */
195
+ async scan(scanOptions) {
196
+ const { target, templates, exec } = scanOptions;
197
+ if (exec) {
198
+ return await runNuclei({ target, templates, exec });
199
+ }
200
+ return [];
201
+ },
202
+
203
+ /**
204
+ * Test for SQL injection
205
+ * @param {Object} testOptions - Test options
206
+ * @returns {Promise<Object>} Test result
207
+ */
208
+ async testSqli(testOptions) {
209
+ return await testSqlInjection(testOptions);
210
+ },
211
+
212
+ /**
213
+ * Test for XSS
214
+ * @param {Object} testOptions - Test options
215
+ * @returns {Promise<Object>} Test result
216
+ */
217
+ async testXss(testOptions) {
218
+ return await testXss(testOptions);
219
+ },
220
+
221
+ /**
222
+ * Test for auth bypass
223
+ * @param {Object} testOptions - Test options
224
+ * @returns {Promise<Object>} Test result
225
+ */
226
+ async testAuthBypass(testOptions) {
227
+ return await testAuthBypass(testOptions);
228
+ }
229
+ };
230
+ }