qa360 1.0.4 → 1.1.1

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 (108) hide show
  1. package/dist/commands/history.js +1 -1
  2. package/dist/commands/pack.js +1 -1
  3. package/dist/commands/run.d.ts +1 -1
  4. package/dist/commands/run.d.ts.map +1 -1
  5. package/dist/commands/run.js +1 -1
  6. package/dist/commands/secrets.js +1 -1
  7. package/dist/commands/serve.js +1 -1
  8. package/dist/commands/verify.js +1 -1
  9. package/dist/core/adapters/gitleaks-secrets.d.ts +115 -0
  10. package/dist/core/adapters/gitleaks-secrets.d.ts.map +1 -0
  11. package/dist/core/adapters/gitleaks-secrets.js +410 -0
  12. package/dist/core/adapters/k6-perf.d.ts +86 -0
  13. package/dist/core/adapters/k6-perf.d.ts.map +1 -0
  14. package/dist/core/adapters/k6-perf.js +398 -0
  15. package/dist/core/adapters/osv-deps.d.ts +124 -0
  16. package/dist/core/adapters/osv-deps.d.ts.map +1 -0
  17. package/dist/core/adapters/osv-deps.js +372 -0
  18. package/dist/core/adapters/playwright-api.d.ts +82 -0
  19. package/dist/core/adapters/playwright-api.d.ts.map +1 -0
  20. package/dist/core/adapters/playwright-api.js +252 -0
  21. package/dist/core/adapters/playwright-ui.d.ts +115 -0
  22. package/dist/core/adapters/playwright-ui.d.ts.map +1 -0
  23. package/dist/core/adapters/playwright-ui.js +346 -0
  24. package/dist/core/adapters/semgrep-sast.d.ts +100 -0
  25. package/dist/core/adapters/semgrep-sast.d.ts.map +1 -0
  26. package/dist/core/adapters/semgrep-sast.js +322 -0
  27. package/dist/core/adapters/zap-dast.d.ts +134 -0
  28. package/dist/core/adapters/zap-dast.d.ts.map +1 -0
  29. package/dist/core/adapters/zap-dast.js +424 -0
  30. package/dist/core/hooks/compose.d.ts +62 -0
  31. package/dist/core/hooks/compose.d.ts.map +1 -0
  32. package/dist/core/hooks/compose.js +225 -0
  33. package/dist/core/hooks/runner.d.ts +69 -0
  34. package/dist/core/hooks/runner.d.ts.map +1 -0
  35. package/dist/core/hooks/runner.js +303 -0
  36. package/dist/core/index.d.ts +74 -0
  37. package/dist/core/index.d.ts.map +1 -0
  38. package/dist/core/index.js +39 -0
  39. package/dist/core/pack/migrator.d.ts +52 -0
  40. package/dist/core/pack/migrator.d.ts.map +1 -0
  41. package/dist/core/pack/migrator.js +304 -0
  42. package/dist/core/pack/validator.d.ts +43 -0
  43. package/dist/core/pack/validator.d.ts.map +1 -0
  44. package/dist/core/pack/validator.js +292 -0
  45. package/dist/core/proof/bundle.d.ts +138 -0
  46. package/dist/core/proof/bundle.d.ts.map +1 -0
  47. package/dist/core/proof/bundle.js +160 -0
  48. package/dist/core/proof/canonicalize.d.ts +48 -0
  49. package/dist/core/proof/canonicalize.d.ts.map +1 -0
  50. package/dist/core/proof/canonicalize.js +105 -0
  51. package/dist/core/proof/index.d.ts +14 -0
  52. package/dist/core/proof/index.d.ts.map +1 -0
  53. package/dist/core/proof/index.js +18 -0
  54. package/dist/core/proof/schema.d.ts +218 -0
  55. package/dist/core/proof/schema.d.ts.map +1 -0
  56. package/dist/core/proof/schema.js +263 -0
  57. package/dist/core/proof/signer.d.ts +112 -0
  58. package/dist/core/proof/signer.d.ts.map +1 -0
  59. package/dist/core/proof/signer.js +226 -0
  60. package/dist/core/proof/verifier.d.ts +98 -0
  61. package/dist/core/proof/verifier.d.ts.map +1 -0
  62. package/dist/core/proof/verifier.js +302 -0
  63. package/dist/core/runner/phase3-runner.d.ts +102 -0
  64. package/dist/core/runner/phase3-runner.d.ts.map +1 -0
  65. package/dist/core/runner/phase3-runner.js +471 -0
  66. package/dist/core/secrets/crypto.d.ts +76 -0
  67. package/dist/core/secrets/crypto.d.ts.map +1 -0
  68. package/dist/core/secrets/crypto.js +225 -0
  69. package/dist/core/secrets/manager.d.ts +77 -0
  70. package/dist/core/secrets/manager.d.ts.map +1 -0
  71. package/dist/core/secrets/manager.js +219 -0
  72. package/dist/core/security/redaction-patterns-extended.d.ts +28 -0
  73. package/dist/core/security/redaction-patterns-extended.d.ts.map +1 -0
  74. package/dist/core/security/redaction-patterns-extended.js +247 -0
  75. package/dist/core/security/redactor.d.ts +72 -0
  76. package/dist/core/security/redactor.d.ts.map +1 -0
  77. package/dist/core/security/redactor.js +279 -0
  78. package/dist/core/serve/diagnostics-collector.d.ts +33 -0
  79. package/dist/core/serve/diagnostics-collector.d.ts.map +1 -0
  80. package/dist/core/serve/diagnostics-collector.js +149 -0
  81. package/dist/core/serve/health-checker.d.ts +45 -0
  82. package/dist/core/serve/health-checker.d.ts.map +1 -0
  83. package/dist/core/serve/health-checker.js +219 -0
  84. package/dist/core/serve/index.d.ts +9 -0
  85. package/dist/core/serve/index.d.ts.map +1 -0
  86. package/dist/core/serve/index.js +8 -0
  87. package/dist/core/serve/metrics-collector.d.ts +25 -0
  88. package/dist/core/serve/metrics-collector.d.ts.map +1 -0
  89. package/dist/core/serve/metrics-collector.js +322 -0
  90. package/dist/core/serve/process-manager.d.ts +37 -0
  91. package/dist/core/serve/process-manager.d.ts.map +1 -0
  92. package/dist/core/serve/process-manager.js +213 -0
  93. package/dist/core/serve/server.d.ts +37 -0
  94. package/dist/core/serve/server.d.ts.map +1 -0
  95. package/dist/core/serve/server.js +191 -0
  96. package/dist/core/types/pack-v1.d.ts +162 -0
  97. package/dist/core/types/pack-v1.d.ts.map +1 -0
  98. package/dist/core/types/pack-v1.js +5 -0
  99. package/dist/core/types/trust-score.d.ts +70 -0
  100. package/dist/core/types/trust-score.d.ts.map +1 -0
  101. package/dist/core/types/trust-score.js +191 -0
  102. package/dist/core/vault/cas.d.ts +87 -0
  103. package/dist/core/vault/cas.d.ts.map +1 -0
  104. package/dist/core/vault/cas.js +255 -0
  105. package/dist/core/vault/index.d.ts +205 -0
  106. package/dist/core/vault/index.d.ts.map +1 -0
  107. package/dist/core/vault/index.js +631 -0
  108. package/package.json +13 -6
@@ -0,0 +1,322 @@
1
+ /**
2
+ * QA360 Semgrep SAST Adapter (Socle OOTB)
3
+ * Static Application Security Testing with configurable severity thresholds
4
+ */
5
+ import { spawn } from 'child_process';
6
+ import { existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { SecurityRedactor } from '../security/redactor.js';
9
+ export class SemgrepSastAdapter {
10
+ redactor;
11
+ constructor() {
12
+ this.redactor = SecurityRedactor.forLogs();
13
+ }
14
+ /**
15
+ * Execute Semgrep SAST scan
16
+ */
17
+ async runSastScan(config) {
18
+ try {
19
+ console.log(`🔍 Running Semgrep SAST scan (${config.paths?.join(', ') || 'default paths'})`);
20
+ // Check if Semgrep is available
21
+ const availability = await SemgrepSastAdapter.isAvailable();
22
+ if (!availability.available) {
23
+ return {
24
+ success: false,
25
+ findings: [],
26
+ summary: this.getDefaultSummary(),
27
+ thresholds: this.getDefaultThresholds(config.security),
28
+ error: availability.error
29
+ };
30
+ }
31
+ // Execute Semgrep
32
+ const result = await this.executeSemgrep(config);
33
+ return result;
34
+ }
35
+ catch (error) {
36
+ return {
37
+ success: false,
38
+ findings: [],
39
+ summary: this.getDefaultSummary(),
40
+ thresholds: this.getDefaultThresholds(config.security),
41
+ error: this.redactor.redact(error instanceof Error ? error.message : 'Unknown error')
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * Execute Semgrep command
47
+ */
48
+ async executeSemgrep(config) {
49
+ return new Promise((resolve) => {
50
+ let output = '';
51
+ let error = '';
52
+ const rules = config.rules || ['auto'];
53
+ const paths = config.paths || ['.'];
54
+ const args = [
55
+ '--config', rules.join(','),
56
+ '--json',
57
+ '--no-git-ignore', // Include all files
58
+ '--timeout', '60',
59
+ ...paths
60
+ ];
61
+ // Add custom config if specified
62
+ if (config.configFile && existsSync(join(config.workingDir, config.configFile))) {
63
+ args.unshift('--config', config.configFile);
64
+ }
65
+ const child = spawn('semgrep', args, {
66
+ cwd: config.workingDir,
67
+ stdio: ['ignore', 'pipe', 'pipe']
68
+ });
69
+ const timeout = setTimeout(() => {
70
+ child.kill('SIGKILL');
71
+ resolve({
72
+ success: false,
73
+ findings: [],
74
+ summary: this.getDefaultSummary(),
75
+ thresholds: this.getDefaultThresholds(config.security),
76
+ error: `Semgrep scan timed out after ${config.timeout || 120000}ms`
77
+ });
78
+ }, config.timeout || 120000);
79
+ if (child.stdout) {
80
+ child.stdout.on('data', (data) => {
81
+ output += data.toString();
82
+ });
83
+ }
84
+ if (child.stderr) {
85
+ child.stderr.on('data', (data) => {
86
+ error += data.toString();
87
+ });
88
+ }
89
+ child.on('close', (code) => {
90
+ clearTimeout(timeout);
91
+ // Semgrep returns 0 for no findings, 1 for findings, 2+ for errors
92
+ if (code === 0 || code === 1) {
93
+ const result = this.parseSemgrepResults(output, config);
94
+ resolve(result);
95
+ }
96
+ else {
97
+ resolve({
98
+ success: false,
99
+ findings: [],
100
+ summary: this.getDefaultSummary(),
101
+ thresholds: this.getDefaultThresholds(config.security),
102
+ error: this.redactor.redact(error || `Semgrep exited with code ${code}`),
103
+ rawOutput: this.redactor.redact(output)
104
+ });
105
+ }
106
+ });
107
+ child.on('error', (err) => {
108
+ clearTimeout(timeout);
109
+ resolve({
110
+ success: false,
111
+ findings: [],
112
+ summary: this.getDefaultSummary(),
113
+ thresholds: this.getDefaultThresholds(config.security),
114
+ error: `Failed to start Semgrep: ${err.message}`
115
+ });
116
+ });
117
+ });
118
+ }
119
+ /**
120
+ * Parse Semgrep JSON results
121
+ */
122
+ parseSemgrepResults(output, config) {
123
+ try {
124
+ const jsonData = JSON.parse(output);
125
+ const findings = [];
126
+ // Parse findings from results
127
+ if (jsonData.results && Array.isArray(jsonData.results)) {
128
+ for (const result of jsonData.results) {
129
+ const finding = {
130
+ ruleId: result.check_id || 'unknown',
131
+ severity: this.mapSeverity(result.extra?.severity || 'INFO'),
132
+ message: result.extra?.message || result.message || 'Security issue detected',
133
+ file: result.path || 'unknown',
134
+ line: result.start?.line || 0,
135
+ column: result.start?.col || 0,
136
+ code: result.extra?.lines ? result.extra.lines.trim() : undefined,
137
+ fix: result.extra?.fix ? result.extra.fix.trim() : undefined
138
+ };
139
+ findings.push(finding);
140
+ }
141
+ }
142
+ // Calculate summary
143
+ const summary = this.calculateSummary(findings);
144
+ // Check thresholds
145
+ const thresholds = this.checkThresholds(summary, config.security);
146
+ // Determine success based on thresholds
147
+ const success = thresholds.sast_max_high.passed;
148
+ const junit = this.generateJUnit(findings, success);
149
+ return {
150
+ success,
151
+ findings: findings.map(f => ({
152
+ ...f,
153
+ message: this.redactor.redact(f.message),
154
+ code: f.code ? this.redactor.redact(f.code) : undefined,
155
+ fix: f.fix ? this.redactor.redact(f.fix) : undefined
156
+ })),
157
+ summary,
158
+ thresholds,
159
+ rawOutput: this.redactor.redact(output),
160
+ junit
161
+ };
162
+ }
163
+ catch (error) {
164
+ return {
165
+ success: false,
166
+ findings: [],
167
+ summary: this.getDefaultSummary(),
168
+ thresholds: this.getDefaultThresholds(config.security),
169
+ error: `Failed to parse Semgrep results: ${error}`,
170
+ rawOutput: this.redactor.redact(output)
171
+ };
172
+ }
173
+ }
174
+ /**
175
+ * Map Semgrep severity to standard levels
176
+ */
177
+ mapSeverity(severity) {
178
+ const sev = severity.toUpperCase();
179
+ if (sev === 'ERROR' || sev === 'HIGH')
180
+ return 'ERROR';
181
+ if (sev === 'WARNING' || sev === 'MEDIUM')
182
+ return 'WARNING';
183
+ return 'INFO';
184
+ }
185
+ /**
186
+ * Calculate findings summary
187
+ */
188
+ calculateSummary(findings) {
189
+ const summary = {
190
+ total: findings.length,
191
+ critical: 0,
192
+ high: 0,
193
+ medium: 0,
194
+ low: 0,
195
+ info: 0
196
+ };
197
+ for (const finding of findings) {
198
+ switch (finding.severity) {
199
+ case 'ERROR':
200
+ summary.high++;
201
+ break;
202
+ case 'WARNING':
203
+ summary.medium++;
204
+ break;
205
+ case 'INFO':
206
+ summary.info++;
207
+ break;
208
+ }
209
+ }
210
+ return summary;
211
+ }
212
+ /**
213
+ * Check security thresholds
214
+ */
215
+ checkThresholds(summary, security) {
216
+ const maxHigh = security?.sast?.max_high ?? 0; // Default: strict (0 high findings)
217
+ return {
218
+ sast_max_high: {
219
+ passed: summary.high <= maxHigh,
220
+ actual: summary.high,
221
+ budget: maxHigh
222
+ }
223
+ };
224
+ }
225
+ /**
226
+ * Generate JUnit XML
227
+ */
228
+ generateJUnit(findings, success) {
229
+ const timestamp = new Date().toISOString();
230
+ const failures = findings.filter(f => f.severity === 'ERROR').length;
231
+ let junit = `<?xml version="1.0" encoding="UTF-8"?>
232
+ <testsuite name="Semgrep SAST Scan" tests="1" failures="${success ? 0 : 1}" time="0" timestamp="${timestamp}">
233
+ <testcase name="SAST Security Scan" time="0">
234
+ `;
235
+ if (!success) {
236
+ junit += ` <failure message="Security issues found">
237
+ High severity findings: ${findings.filter(f => f.severity === 'ERROR').length}
238
+ Medium severity findings: ${findings.filter(f => f.severity === 'WARNING').length}
239
+ Total findings: ${findings.length}
240
+
241
+ Top findings:
242
+ ${findings.slice(0, 5).map(f => `- ${f.ruleId}: ${f.message} (${f.file}:${f.line})`).join('\n')}
243
+ </failure>
244
+ `;
245
+ }
246
+ junit += ` </testcase>
247
+ </testsuite>`;
248
+ return junit;
249
+ }
250
+ /**
251
+ * Get default summary structure
252
+ */
253
+ getDefaultSummary() {
254
+ return {
255
+ total: 0,
256
+ critical: 0,
257
+ high: 0,
258
+ medium: 0,
259
+ low: 0,
260
+ info: 0
261
+ };
262
+ }
263
+ /**
264
+ * Get default thresholds
265
+ */
266
+ getDefaultThresholds(security) {
267
+ return {
268
+ sast_max_high: {
269
+ passed: true,
270
+ actual: 0,
271
+ budget: security?.sast?.max_high ?? 0
272
+ }
273
+ };
274
+ }
275
+ /**
276
+ * Check if Semgrep is available
277
+ */
278
+ static async isAvailable() {
279
+ return new Promise((resolve) => {
280
+ const child = spawn('semgrep', ['--version'], { stdio: 'pipe' });
281
+ child.on('close', (code) => {
282
+ resolve({
283
+ available: code === 0,
284
+ error: code !== 0 ? 'Semgrep not found. Install with: pip install semgrep' : undefined
285
+ });
286
+ });
287
+ child.on('error', () => {
288
+ resolve({
289
+ available: false,
290
+ error: 'Semgrep not found. Install with: pip install semgrep'
291
+ });
292
+ });
293
+ });
294
+ }
295
+ /**
296
+ * Validate SAST configuration
297
+ */
298
+ static validateConfig(config) {
299
+ const errors = [];
300
+ if (!config.workingDir || !existsSync(config.workingDir)) {
301
+ errors.push('SAST scan requires valid working directory');
302
+ }
303
+ if (config.paths) {
304
+ for (const path of config.paths) {
305
+ const fullPath = join(config.workingDir, path);
306
+ if (!existsSync(fullPath)) {
307
+ errors.push(`SAST scan path not found: ${path}`);
308
+ }
309
+ }
310
+ }
311
+ if (config.configFile) {
312
+ const configPath = join(config.workingDir, config.configFile);
313
+ if (!existsSync(configPath)) {
314
+ errors.push(`Semgrep config file not found: ${config.configFile}`);
315
+ }
316
+ }
317
+ return {
318
+ valid: errors.length === 0,
319
+ errors
320
+ };
321
+ }
322
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * QA360 ZAP DAST Adapter (Sécurité Réelle)
3
+ * OWASP ZAP baseline scan for dynamic application security testing
4
+ */
5
+ import { PackSecurity } from '../types/pack-v1.js';
6
+ export interface ZapDastConfig {
7
+ targetUrl: string;
8
+ security?: PackSecurity;
9
+ timeout?: number;
10
+ scanType?: 'baseline' | 'full' | 'api';
11
+ contextFile?: string;
12
+ excludeUrls?: string[];
13
+ includeUrls?: string[];
14
+ authScript?: string;
15
+ configFile?: string;
16
+ }
17
+ export interface ZapAlert {
18
+ pluginid: string;
19
+ alertRef: string;
20
+ alert: string;
21
+ name: string;
22
+ riskcode: string;
23
+ confidence: string;
24
+ riskdesc: string;
25
+ desc: string;
26
+ instances: Array<{
27
+ uri: string;
28
+ method: string;
29
+ param: string;
30
+ attack: string;
31
+ evidence: string;
32
+ otherinfo: string;
33
+ }>;
34
+ count: string;
35
+ solution: string;
36
+ otherinfo: string;
37
+ reference: string;
38
+ cweid: string;
39
+ wascid: string;
40
+ sourceid: string;
41
+ }
42
+ export interface ZapDastResult {
43
+ success: boolean;
44
+ alerts: ZapAlert[];
45
+ summary: {
46
+ total: number;
47
+ high: number;
48
+ medium: number;
49
+ low: number;
50
+ informational: number;
51
+ by_category: Record<string, number>;
52
+ };
53
+ budgetCheck: {
54
+ high_passed: boolean;
55
+ critical_passed: boolean;
56
+ medium_passed: boolean;
57
+ };
58
+ targetUrl: string;
59
+ scanDuration: number;
60
+ error?: string;
61
+ rawOutput?: string;
62
+ reportPath?: string;
63
+ junit?: string;
64
+ errorCode?: string;
65
+ }
66
+ export declare class ZapDastAdapter {
67
+ private redactor;
68
+ private workingDir;
69
+ constructor(workingDir?: string);
70
+ /**
71
+ * Execute ZAP DAST scan
72
+ */
73
+ runDastScan(config: ZapDastConfig): Promise<ZapDastResult>;
74
+ /**
75
+ * Validate URL format
76
+ */
77
+ private isValidUrl;
78
+ /**
79
+ * Execute ZAP scanner
80
+ */
81
+ private executeZapScan;
82
+ /**
83
+ * Check if Docker should be used for ZAP
84
+ */
85
+ private shouldUseDocker;
86
+ /**
87
+ * Build ZAP command arguments
88
+ */
89
+ private buildZapArgs;
90
+ /**
91
+ * Parse ZAP scan results
92
+ */
93
+ private parseZapResults;
94
+ /**
95
+ * Fallback mock scan when ZAP not available
96
+ */
97
+ private fallbackMockScan;
98
+ /**
99
+ * Calculate alerts summary
100
+ */
101
+ private calculateSummary;
102
+ /**
103
+ * Generate budget check based on security config
104
+ */
105
+ private generateBudgetCheck;
106
+ /**
107
+ * Get empty summary structure
108
+ */
109
+ private getEmptySummary;
110
+ /**
111
+ * Get default budget check structure
112
+ */
113
+ private getDefaultBudgetCheck;
114
+ /**
115
+ * Generate JUnit XML report
116
+ */
117
+ private generateJUnit;
118
+ /**
119
+ * Validate ZAP scan configuration
120
+ */
121
+ static validateConfig(config: ZapDastConfig): {
122
+ valid: boolean;
123
+ errors: string[];
124
+ };
125
+ /**
126
+ * Check if ZAP is available (Docker or local)
127
+ */
128
+ static isAvailable(): Promise<{
129
+ available: boolean;
130
+ method?: 'docker' | 'local';
131
+ error?: string;
132
+ }>;
133
+ }
134
+ //# sourceMappingURL=zap-dast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zap-dast.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/zap-dast.ts"],"names":[],"mappings":"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"}