cipher-security 5.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 (75) hide show
  1. package/bin/cipher.js +465 -0
  2. package/lib/api/billing.js +321 -0
  3. package/lib/api/compliance.js +693 -0
  4. package/lib/api/controls.js +1401 -0
  5. package/lib/api/index.js +49 -0
  6. package/lib/api/marketplace.js +467 -0
  7. package/lib/api/openai-proxy.js +383 -0
  8. package/lib/api/server.js +685 -0
  9. package/lib/autonomous/feedback-loop.js +554 -0
  10. package/lib/autonomous/framework.js +512 -0
  11. package/lib/autonomous/index.js +97 -0
  12. package/lib/autonomous/leaderboard.js +594 -0
  13. package/lib/autonomous/modes/architect.js +412 -0
  14. package/lib/autonomous/modes/blue.js +386 -0
  15. package/lib/autonomous/modes/incident.js +684 -0
  16. package/lib/autonomous/modes/privacy.js +369 -0
  17. package/lib/autonomous/modes/purple.js +294 -0
  18. package/lib/autonomous/modes/recon.js +250 -0
  19. package/lib/autonomous/parallel.js +587 -0
  20. package/lib/autonomous/researcher.js +583 -0
  21. package/lib/autonomous/runner.js +955 -0
  22. package/lib/autonomous/scheduler.js +615 -0
  23. package/lib/autonomous/task-parser.js +127 -0
  24. package/lib/autonomous/validators/forensic.js +266 -0
  25. package/lib/autonomous/validators/osint.js +216 -0
  26. package/lib/autonomous/validators/privacy.js +296 -0
  27. package/lib/autonomous/validators/purple.js +298 -0
  28. package/lib/autonomous/validators/sigma.js +248 -0
  29. package/lib/autonomous/validators/threat-model.js +363 -0
  30. package/lib/benchmark/agent.js +119 -0
  31. package/lib/benchmark/baselines.js +43 -0
  32. package/lib/benchmark/builder.js +143 -0
  33. package/lib/benchmark/config.js +35 -0
  34. package/lib/benchmark/coordinator.js +91 -0
  35. package/lib/benchmark/index.js +20 -0
  36. package/lib/benchmark/llm.js +58 -0
  37. package/lib/benchmark/models.js +137 -0
  38. package/lib/benchmark/reporter.js +103 -0
  39. package/lib/benchmark/runner.js +103 -0
  40. package/lib/benchmark/sandbox.js +96 -0
  41. package/lib/benchmark/scorer.js +32 -0
  42. package/lib/benchmark/solver.js +166 -0
  43. package/lib/benchmark/tools.js +62 -0
  44. package/lib/bot/bot.js +130 -0
  45. package/lib/commands.js +99 -0
  46. package/lib/complexity.js +377 -0
  47. package/lib/config.js +213 -0
  48. package/lib/gateway/client.js +309 -0
  49. package/lib/gateway/commands.js +830 -0
  50. package/lib/gateway/config-validate.js +109 -0
  51. package/lib/gateway/gateway.js +367 -0
  52. package/lib/gateway/index.js +62 -0
  53. package/lib/gateway/mode.js +309 -0
  54. package/lib/gateway/plugins.js +222 -0
  55. package/lib/gateway/prompt.js +214 -0
  56. package/lib/mcp/server.js +262 -0
  57. package/lib/memory/compressor.js +425 -0
  58. package/lib/memory/engine.js +763 -0
  59. package/lib/memory/evolution.js +668 -0
  60. package/lib/memory/index.js +58 -0
  61. package/lib/memory/orchestrator.js +506 -0
  62. package/lib/memory/retriever.js +515 -0
  63. package/lib/memory/synthesizer.js +333 -0
  64. package/lib/pipeline/async-scanner.js +510 -0
  65. package/lib/pipeline/binary-analysis.js +1043 -0
  66. package/lib/pipeline/dom-xss-scanner.js +435 -0
  67. package/lib/pipeline/github-actions.js +792 -0
  68. package/lib/pipeline/index.js +124 -0
  69. package/lib/pipeline/osint.js +498 -0
  70. package/lib/pipeline/sarif.js +373 -0
  71. package/lib/pipeline/scanner.js +880 -0
  72. package/lib/pipeline/template-manager.js +525 -0
  73. package/lib/pipeline/xss-scanner.js +353 -0
  74. package/lib/setup-wizard.js +229 -0
  75. package/package.json +30 -0
@@ -0,0 +1,373 @@
1
+ // Copyright (c) 2026 defconxt. All rights reserved.
2
+ // Licensed under AGPL-3.0 — see LICENSE file for details.
3
+ // CIPHER is a trademark of defconxt.
4
+
5
+ /**
6
+ * CIPHER SARIF Output — Static Analysis Results Interchange Format.
7
+ *
8
+ * Converts CIPHER scan findings into SARIF v2.1.0 for CI/CD integration
9
+ * (GitHub Advanced Security, Azure DevOps, GitLab SAST, etc.).
10
+ */
11
+
12
+ import { writeFileSync, mkdirSync } from 'node:fs';
13
+ import { dirname } from 'node:path';
14
+ import { randomUUID } from 'node:crypto';
15
+
16
+ const SARIF_VERSION = '2.1.0';
17
+ const SARIF_SCHEMA =
18
+ 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json';
19
+
20
+ /**
21
+ * Map CIPHER severity to SARIF level.
22
+ * @param {string} severity
23
+ * @returns {string}
24
+ */
25
+ function severityToLevel(severity) {
26
+ const map = {
27
+ critical: 'error',
28
+ high: 'error',
29
+ medium: 'warning',
30
+ low: 'note',
31
+ info: 'note',
32
+ };
33
+ return map[severity?.toLowerCase()] || 'warning';
34
+ }
35
+
36
+ /**
37
+ * Map CIPHER severity to GitHub security-severity score string.
38
+ * @param {string} severity
39
+ * @returns {string}
40
+ */
41
+ function severityScore(severity) {
42
+ const map = {
43
+ critical: '9.5',
44
+ high: '8.0',
45
+ medium: '5.5',
46
+ low: '3.0',
47
+ info: '1.0',
48
+ };
49
+ return map[severity?.toLowerCase()] || '5.0';
50
+ }
51
+
52
+ /**
53
+ * A SARIF reporting descriptor (rule).
54
+ */
55
+ class SarifRule {
56
+ /**
57
+ * @param {object} opts
58
+ * @param {string} opts.id
59
+ * @param {string} opts.name
60
+ * @param {string} [opts.shortDescription]
61
+ * @param {string} [opts.fullDescription]
62
+ * @param {string} [opts.helpUri]
63
+ * @param {string} [opts.level]
64
+ * @param {string[]} [opts.tags]
65
+ */
66
+ constructor(opts = {}) {
67
+ this.id = opts.id || '';
68
+ this.name = opts.name || '';
69
+ this.shortDescription = opts.shortDescription || '';
70
+ this.fullDescription = opts.fullDescription || '';
71
+ this.helpUri = opts.helpUri || '';
72
+ this.level = opts.level || 'warning';
73
+ this.tags = opts.tags || [];
74
+ }
75
+
76
+ toDict() {
77
+ const rule = {
78
+ id: this.id,
79
+ name: this.name,
80
+ shortDescription: { text: this.shortDescription || this.name },
81
+ };
82
+ if (this.fullDescription) {
83
+ rule.fullDescription = { text: this.fullDescription };
84
+ }
85
+ if (this.helpUri) {
86
+ rule.helpUri = this.helpUri;
87
+ }
88
+ rule.defaultConfiguration = { level: this.level };
89
+ if (this.tags.length > 0) {
90
+ rule.properties = { tags: this.tags };
91
+ }
92
+ return rule;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * A single SARIF result (finding).
98
+ */
99
+ class SarifResult {
100
+ /**
101
+ * @param {object} opts
102
+ * @param {string} opts.ruleId
103
+ * @param {string} opts.message
104
+ * @param {string} [opts.level]
105
+ * @param {string} [opts.uri]
106
+ * @param {number} [opts.startLine]
107
+ * @param {number} [opts.startColumn]
108
+ * @param {number} [opts.endLine]
109
+ * @param {string} [opts.snippet]
110
+ * @param {string} [opts.fingerprint]
111
+ * @param {object} [opts.properties]
112
+ */
113
+ constructor(opts = {}) {
114
+ this.ruleId = opts.ruleId || '';
115
+ this.message = opts.message || '';
116
+ this.level = opts.level || 'warning';
117
+ this.uri = opts.uri || '';
118
+ this.startLine = opts.startLine || 0;
119
+ this.startColumn = opts.startColumn || 0;
120
+ this.endLine = opts.endLine || 0;
121
+ this.snippet = opts.snippet || '';
122
+ this.fingerprint = opts.fingerprint || '';
123
+ this.properties = opts.properties || {};
124
+ }
125
+
126
+ toDict() {
127
+ const result = {
128
+ ruleId: this.ruleId,
129
+ level: this.level,
130
+ message: { text: this.message },
131
+ };
132
+
133
+ if (this.uri || this.startLine) {
134
+ const location = {};
135
+ if (this.uri) {
136
+ location.physicalLocation = {
137
+ artifactLocation: { uri: this.uri },
138
+ };
139
+ if (this.startLine) {
140
+ const region = { startLine: this.startLine };
141
+ if (this.startColumn) region.startColumn = this.startColumn;
142
+ if (this.endLine) region.endLine = this.endLine;
143
+ if (this.snippet) region.snippet = { text: this.snippet };
144
+ location.physicalLocation.region = region;
145
+ }
146
+ }
147
+ result.locations = [location];
148
+ }
149
+
150
+ if (this.fingerprint) {
151
+ result.fingerprints = { 'cipher/v1': this.fingerprint };
152
+ }
153
+
154
+ if (Object.keys(this.properties).length > 0) {
155
+ result.properties = this.properties;
156
+ }
157
+
158
+ return result;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Build a SARIF v2.1.0 report from CIPHER findings.
164
+ */
165
+ class SarifReport {
166
+ /**
167
+ * @param {object} [opts]
168
+ * @param {string} [opts.toolName]
169
+ * @param {string} [opts.toolVersion]
170
+ * @param {string} [opts.toolUri]
171
+ */
172
+ constructor(opts = {}) {
173
+ this.toolName = opts.toolName || 'CIPHER';
174
+ this.toolVersion = opts.toolVersion || '0.0.0';
175
+ this.toolUri = opts.toolUri || 'https://github.com/defconxt/CIPHER';
176
+ /** @type {Map<string, SarifRule>} */
177
+ this._rules = new Map();
178
+ /** @type {SarifResult[]} */
179
+ this._results = [];
180
+ this._invocationStart = new Date().toISOString();
181
+ }
182
+
183
+ /**
184
+ * Register a rule (deduplicates by ID).
185
+ * @param {SarifRule} rule
186
+ */
187
+ addRule(rule) {
188
+ this._rules.set(rule.id, rule);
189
+ }
190
+
191
+ /**
192
+ * Add a finding result.
193
+ * @param {SarifResult} result
194
+ */
195
+ addResult(result) {
196
+ this._results.push(result);
197
+ }
198
+
199
+ /**
200
+ * Convert a CIPHER finding dict to SARIF rule + result.
201
+ *
202
+ * Expected keys: template_id, name, description, severity, host,
203
+ * matched_at, tags, cve_ids, reference
204
+ * @param {object} finding
205
+ */
206
+ addFinding(finding) {
207
+ const ruleId =
208
+ finding.template_id || finding.templateId || finding.id || randomUUID().slice(0, 8);
209
+ const severity = (finding.severity || 'medium').toLowerCase();
210
+ const level = severityToLevel(severity);
211
+
212
+ // Auto-register rule
213
+ if (!this._rules.has(ruleId)) {
214
+ this.addRule(
215
+ new SarifRule({
216
+ id: ruleId,
217
+ name: finding.name || ruleId,
218
+ shortDescription: finding.description || '',
219
+ level,
220
+ tags: finding.tags || [],
221
+ helpUri: finding.reference || '',
222
+ }),
223
+ );
224
+ }
225
+
226
+ // Build result
227
+ const props = {};
228
+ if (finding.cve_ids || finding.cveIds) {
229
+ props.cve = finding.cve_ids || finding.cveIds;
230
+ }
231
+ if (finding.severity) {
232
+ props['security-severity'] = severityScore(severity);
233
+ }
234
+
235
+ this.addResult(
236
+ new SarifResult({
237
+ ruleId,
238
+ message: `${finding.name || 'Finding'} at ${finding.host || finding.matched_at || finding.matchedAt || 'unknown'}`,
239
+ level,
240
+ uri: finding.matched_at || finding.matchedAt || finding.host || '',
241
+ properties: Object.keys(props).length > 0 ? props : {},
242
+ }),
243
+ );
244
+ }
245
+
246
+ /**
247
+ * Convert a CIPHER diff analysis finding to SARIF.
248
+ *
249
+ * Expected keys: type, severity, file, line, description, snippet
250
+ * @param {object} finding
251
+ */
252
+ addDiffFinding(finding) {
253
+ const ruleId = `cipher-diff-${finding.type || 'generic'}`;
254
+ const severity = (finding.severity || 'medium').toLowerCase();
255
+ const level = severityToLevel(severity);
256
+
257
+ if (!this._rules.has(ruleId)) {
258
+ this.addRule(
259
+ new SarifRule({
260
+ id: ruleId,
261
+ name: `Security Diff: ${finding.type || 'issue'}`,
262
+ shortDescription:
263
+ finding.description || 'Security-relevant code change detected',
264
+ level,
265
+ tags: ['security', 'diff-analysis'],
266
+ }),
267
+ );
268
+ }
269
+
270
+ this.addResult(
271
+ new SarifResult({
272
+ ruleId,
273
+ message: finding.description || 'Security-relevant change',
274
+ level,
275
+ uri: finding.file || '',
276
+ startLine: finding.line || 0,
277
+ snippet: finding.snippet || '',
278
+ properties: { 'security-severity': severityScore(severity) },
279
+ }),
280
+ );
281
+ }
282
+
283
+ /**
284
+ * Build the complete SARIF JSON structure.
285
+ * @returns {object}
286
+ */
287
+ toDict() {
288
+ const run = {
289
+ tool: {
290
+ driver: {
291
+ name: this.toolName,
292
+ version: this.toolVersion,
293
+ informationUri: this.toolUri,
294
+ rules: Array.from(this._rules.values()).map((r) => r.toDict()),
295
+ },
296
+ },
297
+ invocations: [
298
+ {
299
+ executionSuccessful: true,
300
+ startTimeUtc: this._invocationStart,
301
+ endTimeUtc: new Date().toISOString(),
302
+ },
303
+ ],
304
+ results: this._results.map((r) => r.toDict()),
305
+ };
306
+
307
+ return {
308
+ $schema: SARIF_SCHEMA,
309
+ version: SARIF_VERSION,
310
+ runs: [run],
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Serialize to JSON string.
316
+ * @param {number} [indent=2]
317
+ * @returns {string}
318
+ */
319
+ toJson(indent = 2) {
320
+ return JSON.stringify(this.toDict(), null, indent);
321
+ }
322
+
323
+ /**
324
+ * Write SARIF to file and return the path.
325
+ * @param {string} path
326
+ * @returns {string}
327
+ */
328
+ write(path) {
329
+ mkdirSync(dirname(path), { recursive: true });
330
+ writeFileSync(path, this.toJson());
331
+ return path;
332
+ }
333
+
334
+ /** @returns {number} */
335
+ get resultCount() {
336
+ return this._results.length;
337
+ }
338
+
339
+ /** @returns {number} */
340
+ get ruleCount() {
341
+ return this._rules.size;
342
+ }
343
+
344
+ /**
345
+ * Return a summary of the report.
346
+ * @returns {object}
347
+ */
348
+ summary() {
349
+ const byLevel = {};
350
+ for (const r of this._results) {
351
+ byLevel[r.level] = (byLevel[r.level] || 0) + 1;
352
+ }
353
+ return {
354
+ rules: this.ruleCount,
355
+ results: this.resultCount,
356
+ by_level: byLevel,
357
+ };
358
+ }
359
+ }
360
+
361
+ export {
362
+ // Constants
363
+ SARIF_VERSION,
364
+ SARIF_SCHEMA,
365
+ // Helpers
366
+ severityToLevel,
367
+ severityScore,
368
+ // Data classes
369
+ SarifRule,
370
+ SarifResult,
371
+ // Report
372
+ SarifReport,
373
+ };