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.
- package/bin/cipher.js +465 -0
- package/lib/api/billing.js +321 -0
- package/lib/api/compliance.js +693 -0
- package/lib/api/controls.js +1401 -0
- package/lib/api/index.js +49 -0
- package/lib/api/marketplace.js +467 -0
- package/lib/api/openai-proxy.js +383 -0
- package/lib/api/server.js +685 -0
- package/lib/autonomous/feedback-loop.js +554 -0
- package/lib/autonomous/framework.js +512 -0
- package/lib/autonomous/index.js +97 -0
- package/lib/autonomous/leaderboard.js +594 -0
- package/lib/autonomous/modes/architect.js +412 -0
- package/lib/autonomous/modes/blue.js +386 -0
- package/lib/autonomous/modes/incident.js +684 -0
- package/lib/autonomous/modes/privacy.js +369 -0
- package/lib/autonomous/modes/purple.js +294 -0
- package/lib/autonomous/modes/recon.js +250 -0
- package/lib/autonomous/parallel.js +587 -0
- package/lib/autonomous/researcher.js +583 -0
- package/lib/autonomous/runner.js +955 -0
- package/lib/autonomous/scheduler.js +615 -0
- package/lib/autonomous/task-parser.js +127 -0
- package/lib/autonomous/validators/forensic.js +266 -0
- package/lib/autonomous/validators/osint.js +216 -0
- package/lib/autonomous/validators/privacy.js +296 -0
- package/lib/autonomous/validators/purple.js +298 -0
- package/lib/autonomous/validators/sigma.js +248 -0
- package/lib/autonomous/validators/threat-model.js +363 -0
- package/lib/benchmark/agent.js +119 -0
- package/lib/benchmark/baselines.js +43 -0
- package/lib/benchmark/builder.js +143 -0
- package/lib/benchmark/config.js +35 -0
- package/lib/benchmark/coordinator.js +91 -0
- package/lib/benchmark/index.js +20 -0
- package/lib/benchmark/llm.js +58 -0
- package/lib/benchmark/models.js +137 -0
- package/lib/benchmark/reporter.js +103 -0
- package/lib/benchmark/runner.js +103 -0
- package/lib/benchmark/sandbox.js +96 -0
- package/lib/benchmark/scorer.js +32 -0
- package/lib/benchmark/solver.js +166 -0
- package/lib/benchmark/tools.js +62 -0
- package/lib/bot/bot.js +130 -0
- package/lib/commands.js +99 -0
- package/lib/complexity.js +377 -0
- package/lib/config.js +213 -0
- package/lib/gateway/client.js +309 -0
- package/lib/gateway/commands.js +830 -0
- package/lib/gateway/config-validate.js +109 -0
- package/lib/gateway/gateway.js +367 -0
- package/lib/gateway/index.js +62 -0
- package/lib/gateway/mode.js +309 -0
- package/lib/gateway/plugins.js +222 -0
- package/lib/gateway/prompt.js +214 -0
- package/lib/mcp/server.js +262 -0
- package/lib/memory/compressor.js +425 -0
- package/lib/memory/engine.js +763 -0
- package/lib/memory/evolution.js +668 -0
- package/lib/memory/index.js +58 -0
- package/lib/memory/orchestrator.js +506 -0
- package/lib/memory/retriever.js +515 -0
- package/lib/memory/synthesizer.js +333 -0
- package/lib/pipeline/async-scanner.js +510 -0
- package/lib/pipeline/binary-analysis.js +1043 -0
- package/lib/pipeline/dom-xss-scanner.js +435 -0
- package/lib/pipeline/github-actions.js +792 -0
- package/lib/pipeline/index.js +124 -0
- package/lib/pipeline/osint.js +498 -0
- package/lib/pipeline/sarif.js +373 -0
- package/lib/pipeline/scanner.js +880 -0
- package/lib/pipeline/template-manager.js +525 -0
- package/lib/pipeline/xss-scanner.js +353 -0
- package/lib/setup-wizard.js +229 -0
- 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
|
+
};
|