cipher-security 2.0.8 → 2.1.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 +1 -1
- package/lib/agent-runtime/handlers/architect.js +199 -0
- package/lib/agent-runtime/handlers/base.js +240 -0
- package/lib/agent-runtime/handlers/blue.js +220 -0
- package/lib/agent-runtime/handlers/incident.js +161 -0
- package/lib/agent-runtime/handlers/privacy.js +190 -0
- package/lib/agent-runtime/handlers/purple.js +209 -0
- package/lib/agent-runtime/handlers/recon.js +174 -0
- package/lib/agent-runtime/handlers/red.js +246 -0
- package/lib/agent-runtime/handlers/researcher.js +170 -0
- package/lib/agent-runtime/handlers.js +35 -0
- package/lib/agent-runtime/index.js +196 -0
- package/lib/agent-runtime/parser.js +316 -0
- package/lib/autonomous/feedback-loop.js +13 -6
- package/lib/autonomous/modes/red.js +557 -0
- package/lib/autonomous/modes/researcher.js +322 -0
- package/lib/autonomous/researcher.js +12 -45
- package/lib/autonomous/runner.js +9 -537
- package/package.json +1 -1
|
@@ -0,0 +1,322 @@
|
|
|
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
|
+
* RESEARCHER mode agent — Security Research & Analysis.
|
|
7
|
+
*
|
|
8
|
+
* Provides CVE analysis, vulnerability research, reverse engineering support,
|
|
9
|
+
* and threat landscape mapping. Tools focus on structured analysis and
|
|
10
|
+
* knowledge extraction rather than active exploitation.
|
|
11
|
+
*
|
|
12
|
+
* @module autonomous/modes/researcher
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { ModeAgentConfig, ToolRegistry } from '../framework.js';
|
|
16
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
17
|
+
import { join, dirname } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
|
|
22
|
+
const debug = process.env.CIPHER_DEBUG === '1'
|
|
23
|
+
? (/** @type {string} */ msg) => process.stderr.write(`[researcher-mode] ${msg}\n`)
|
|
24
|
+
: () => {};
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Tool handlers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Analyze a CVE by ID — extract structured vulnerability information.
|
|
32
|
+
* @param {*} context
|
|
33
|
+
* @param {Object} toolInput
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
function _researcherAnalyzeCve(context, toolInput) {
|
|
37
|
+
const cveId = (toolInput.cve_id || '').toUpperCase();
|
|
38
|
+
if (!/^CVE-\d{4}-\d{4,}$/.test(cveId)) {
|
|
39
|
+
return `Invalid CVE ID format: "${cveId}". Expected format: CVE-YYYY-NNNNN`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return JSON.stringify({
|
|
43
|
+
cve_id: cveId,
|
|
44
|
+
analysis_template: {
|
|
45
|
+
summary: `Analyze ${cveId} — provide description, affected software, CVSS score, exploitability, patch status`,
|
|
46
|
+
sections: [
|
|
47
|
+
'Vulnerability Description',
|
|
48
|
+
'Affected Versions',
|
|
49
|
+
'CVSS Score & Vector',
|
|
50
|
+
'Exploitability Assessment',
|
|
51
|
+
'Proof of Concept Status',
|
|
52
|
+
'Patch / Mitigation Status',
|
|
53
|
+
'Detection Opportunities',
|
|
54
|
+
'ATT&CK Technique Mapping',
|
|
55
|
+
'Recommendations',
|
|
56
|
+
],
|
|
57
|
+
data_sources: [
|
|
58
|
+
`https://nvd.nist.gov/vuln/detail/${cveId}`,
|
|
59
|
+
`https://cve.mitre.org/cgi-bin/cvename.cgi?name=${cveId}`,
|
|
60
|
+
'Vendor advisories',
|
|
61
|
+
'ExploitDB / PacketStorm',
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
instruction: `Research ${cveId} using available knowledge and web search. Fill in each section with findings. Rate confidence per claim.`,
|
|
65
|
+
}, null, 2);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Search CIPHER knowledge base for relevant security research material.
|
|
70
|
+
* @param {*} context
|
|
71
|
+
* @param {Object} toolInput
|
|
72
|
+
* @returns {string}
|
|
73
|
+
*/
|
|
74
|
+
function _researcherSearchKnowledge(context, toolInput) {
|
|
75
|
+
const query = (toolInput.query || '').toLowerCase();
|
|
76
|
+
if (!query) {
|
|
77
|
+
return 'Error: query is required';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const knowledgeDir = join(__dirname, '..', '..', '..', 'knowledge');
|
|
81
|
+
const results = [];
|
|
82
|
+
|
|
83
|
+
if (!existsSync(knowledgeDir)) {
|
|
84
|
+
return JSON.stringify({ query, results: [], note: 'Knowledge directory not found' });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const files = readdirSync(knowledgeDir);
|
|
89
|
+
const queryTerms = query.split(/\s+/).filter(t => t.length > 2);
|
|
90
|
+
|
|
91
|
+
for (const file of files) {
|
|
92
|
+
if (!file.endsWith('.md')) continue;
|
|
93
|
+
const filePath = join(knowledgeDir, file);
|
|
94
|
+
try {
|
|
95
|
+
const content = readFileSync(filePath, 'utf8');
|
|
96
|
+
const lower = content.toLowerCase();
|
|
97
|
+
|
|
98
|
+
// Score by term matches
|
|
99
|
+
let score = 0;
|
|
100
|
+
for (const term of queryTerms) {
|
|
101
|
+
const matches = (lower.match(new RegExp(term, 'g')) || []).length;
|
|
102
|
+
score += Math.min(matches, 10);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (score > 0) {
|
|
106
|
+
const headingMatch = content.match(/^# (.+)$/m);
|
|
107
|
+
const title = headingMatch ? headingMatch[1] : file;
|
|
108
|
+
|
|
109
|
+
results.push({
|
|
110
|
+
file,
|
|
111
|
+
title,
|
|
112
|
+
score,
|
|
113
|
+
preview: content.slice(0, 200).replace(/\n/g, ' ').trim(),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
// skip unreadable files
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// knowledge dir scan failed
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
results.sort((a, b) => b.score - a.score);
|
|
125
|
+
|
|
126
|
+
return JSON.stringify({
|
|
127
|
+
query,
|
|
128
|
+
results: results.slice(0, 10),
|
|
129
|
+
totalMatches: results.length,
|
|
130
|
+
}, null, 2);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Generate a structured research report template.
|
|
135
|
+
* @param {*} context
|
|
136
|
+
* @param {Object} toolInput
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
function _researcherWriteReport(context, toolInput) {
|
|
140
|
+
const topic = toolInput.topic || 'Security Research';
|
|
141
|
+
const findings = toolInput.findings || [];
|
|
142
|
+
const recommendations = toolInput.recommendations || [];
|
|
143
|
+
const confidence = toolInput.confidence || 'MEDIUM';
|
|
144
|
+
|
|
145
|
+
const report = {
|
|
146
|
+
title: topic,
|
|
147
|
+
generated: new Date().toISOString(),
|
|
148
|
+
confidence,
|
|
149
|
+
sections: {
|
|
150
|
+
executive_summary: `Research analysis of: ${topic}`,
|
|
151
|
+
findings: findings.length > 0 ? findings : ['No findings provided — populate from research'],
|
|
152
|
+
recommendations: recommendations.length > 0 ? recommendations : ['No recommendations provided'],
|
|
153
|
+
attack_surface: 'Map relevant ATT&CK techniques',
|
|
154
|
+
detection_opportunities: 'Identify defensive detection points',
|
|
155
|
+
references: 'Cite sources with confidence ratings',
|
|
156
|
+
},
|
|
157
|
+
metadata: {
|
|
158
|
+
researcher: 'CIPHER Autonomous Researcher',
|
|
159
|
+
mode: 'RESEARCHER',
|
|
160
|
+
format: 'structured-json',
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
return JSON.stringify(report, null, 2);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Tool schemas
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
const _RESEARCHER_ANALYZE_CVE_SCHEMA = {
|
|
172
|
+
name: 'analyze_cve',
|
|
173
|
+
description:
|
|
174
|
+
'Analyze a CVE by ID. Returns a structured analysis template with sections to investigate. ' +
|
|
175
|
+
'Use this to begin CVE research — it provides the framework, then fill sections with findings.',
|
|
176
|
+
input_schema: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
properties: {
|
|
179
|
+
cve_id: {
|
|
180
|
+
type: 'string',
|
|
181
|
+
description: 'CVE identifier (e.g., CVE-2024-1234)',
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
required: ['cve_id'],
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const _RESEARCHER_SEARCH_KNOWLEDGE_SCHEMA = {
|
|
189
|
+
name: 'search_knowledge',
|
|
190
|
+
description:
|
|
191
|
+
'Search the CIPHER knowledge base for security research material. ' +
|
|
192
|
+
'Returns matching documents ranked by relevance with previews.',
|
|
193
|
+
input_schema: {
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {
|
|
196
|
+
query: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
description: 'Search query (e.g., "buffer overflow exploitation", "ransomware detection")',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
required: ['query'],
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const _RESEARCHER_WRITE_REPORT_SCHEMA = {
|
|
206
|
+
name: 'write_research_report',
|
|
207
|
+
description:
|
|
208
|
+
'Generate a structured security research report. ' +
|
|
209
|
+
'Provide topic, findings, and recommendations to produce a formatted report.',
|
|
210
|
+
input_schema: {
|
|
211
|
+
type: 'object',
|
|
212
|
+
properties: {
|
|
213
|
+
topic: {
|
|
214
|
+
type: 'string',
|
|
215
|
+
description: 'Research topic or title',
|
|
216
|
+
},
|
|
217
|
+
findings: {
|
|
218
|
+
type: 'array',
|
|
219
|
+
items: { type: 'string' },
|
|
220
|
+
description: 'List of research findings',
|
|
221
|
+
},
|
|
222
|
+
recommendations: {
|
|
223
|
+
type: 'array',
|
|
224
|
+
items: { type: 'string' },
|
|
225
|
+
description: 'List of actionable recommendations',
|
|
226
|
+
},
|
|
227
|
+
confidence: {
|
|
228
|
+
type: 'string',
|
|
229
|
+
enum: ['HIGH', 'MEDIUM', 'LOW'],
|
|
230
|
+
description: 'Overall confidence level in the research',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
required: ['topic'],
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// System prompt
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
const _RESEARCHER_SYSTEM_PROMPT = `\
|
|
242
|
+
You are an expert security researcher performing in-depth analysis on a security topic. \
|
|
243
|
+
Your goal is to produce thorough, actionable research with clear confidence ratings.
|
|
244
|
+
|
|
245
|
+
## Research Protocol
|
|
246
|
+
|
|
247
|
+
1. **Scope the topic** — understand what's being asked and what deliverables are needed
|
|
248
|
+
2. **Search knowledge** — use search_knowledge to find relevant CIPHER docs
|
|
249
|
+
3. **Analyze** — for CVEs use analyze_cve, for other topics use structured analysis
|
|
250
|
+
4. **Synthesize** — combine findings into a coherent narrative with ATT&CK mappings
|
|
251
|
+
5. **Report** — use write_research_report to produce the final structured output
|
|
252
|
+
|
|
253
|
+
## Confidence Ratings
|
|
254
|
+
Tag every substantive claim:
|
|
255
|
+
- **[CONFIRMED]** — directly supported by evidence or established literature
|
|
256
|
+
- **[INFERRED]** — logically derived; reasonable but verify
|
|
257
|
+
- **[EXTERNAL]** — requires knowledge beyond current material; source cited
|
|
258
|
+
- **[UNCERTAIN]** — insufficient data; states what additional information is needed
|
|
259
|
+
|
|
260
|
+
## Output Format
|
|
261
|
+
Your research must include:
|
|
262
|
+
- Executive summary (2-3 sentences)
|
|
263
|
+
- Detailed findings with evidence
|
|
264
|
+
- ATT&CK technique mappings where applicable
|
|
265
|
+
- Actionable recommendations ordered by priority
|
|
266
|
+
- Detection opportunities for defensive teams
|
|
267
|
+
- Confidence assessment per finding
|
|
268
|
+
|
|
269
|
+
## Important Notes
|
|
270
|
+
- Be thorough but concise — depth over breadth
|
|
271
|
+
- Cite specific sources, files, CVEs, or standards
|
|
272
|
+
- Flag gaps in knowledge explicitly rather than guessing
|
|
273
|
+
- If the topic requires current information, note what needs web search verification
|
|
274
|
+
`;
|
|
275
|
+
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Factory
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Build a RESEARCHER-mode ModeAgentConfig.
|
|
282
|
+
* @returns {ModeAgentConfig}
|
|
283
|
+
*/
|
|
284
|
+
function _makeResearcherConfig() {
|
|
285
|
+
const reg = new ToolRegistry();
|
|
286
|
+
reg.register('analyze_cve', _RESEARCHER_ANALYZE_CVE_SCHEMA, _researcherAnalyzeCve);
|
|
287
|
+
reg.register('search_knowledge', _RESEARCHER_SEARCH_KNOWLEDGE_SCHEMA, _researcherSearchKnowledge);
|
|
288
|
+
reg.register('write_research_report', _RESEARCHER_WRITE_REPORT_SCHEMA, _researcherWriteReport);
|
|
289
|
+
|
|
290
|
+
return new ModeAgentConfig({
|
|
291
|
+
mode: 'RESEARCHER',
|
|
292
|
+
toolRegistry: reg,
|
|
293
|
+
systemPromptTemplate: _RESEARCHER_SYSTEM_PROMPT,
|
|
294
|
+
validator: null, // No structured validation — output is freeform research
|
|
295
|
+
maxTurns: 20,
|
|
296
|
+
requiresSandbox: false,
|
|
297
|
+
completionCheck: null,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
// Registration
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Register RESEARCHER mode with the given registerMode function.
|
|
307
|
+
* @param {Function} registerMode
|
|
308
|
+
*/
|
|
309
|
+
export function register(registerMode) {
|
|
310
|
+
registerMode('RESEARCHER', _makeResearcherConfig);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// ---------------------------------------------------------------------------
|
|
314
|
+
// Exports for testing
|
|
315
|
+
// ---------------------------------------------------------------------------
|
|
316
|
+
|
|
317
|
+
export {
|
|
318
|
+
_makeResearcherConfig,
|
|
319
|
+
_researcherAnalyzeCve,
|
|
320
|
+
_researcherSearchKnowledge,
|
|
321
|
+
_researcherWriteReport,
|
|
322
|
+
};
|
|
@@ -318,47 +318,9 @@ node scripts/agent.js report --format json
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
function _generateAgentPy(domain, techniqueName) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
import argparse
|
|
326
|
-
import json
|
|
327
|
-
import sys
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
def ${funcPrefix}_analyze(target, verbose=False):
|
|
331
|
-
"""Analyze a target for ${techniqueName} indicators."""
|
|
332
|
-
results = {
|
|
333
|
-
"action": "analyze",
|
|
334
|
-
"technique": "${techniqueName}",
|
|
335
|
-
"domain": "${domain}",
|
|
336
|
-
"target": target,
|
|
337
|
-
"findings": [],
|
|
338
|
-
"risk_level": "medium",
|
|
339
|
-
}
|
|
340
|
-
if verbose:
|
|
341
|
-
results["debug"] = {"verbose": True}
|
|
342
|
-
return results
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
def main():
|
|
346
|
-
parser = argparse.ArgumentParser(description="${techniqueName} agent")
|
|
347
|
-
parser.add_argument("--target", required=True)
|
|
348
|
-
parser.add_argument("--verbose", action="store_true")
|
|
349
|
-
parser.add_argument("--format", choices=["json", "text"], default="json")
|
|
350
|
-
args = parser.parse_args()
|
|
351
|
-
|
|
352
|
-
result = ${funcPrefix}_analyze(args.target, args.verbose)
|
|
353
|
-
if args.format == "json":
|
|
354
|
-
print(json.dumps(result, indent=2))
|
|
355
|
-
else:
|
|
356
|
-
for k, v in result.items():
|
|
357
|
-
print(f"{k}: {v}")
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if __name__ == "__main__":
|
|
361
|
-
main()
|
|
321
|
+
return `#!/usr/bin/env node
|
|
322
|
+
import { run } from '../../../../../cli/lib/agent-runtime/index.js';
|
|
323
|
+
run(import.meta.url);
|
|
362
324
|
`;
|
|
363
325
|
}
|
|
364
326
|
|
|
@@ -473,9 +435,12 @@ export class AutonomousResearcher {
|
|
|
473
435
|
}
|
|
474
436
|
|
|
475
437
|
static _checkCompiles(script) {
|
|
476
|
-
//
|
|
477
|
-
|
|
478
|
-
|
|
438
|
+
// Verify agent.js is either a runtime wrapper or a standalone Node.js script
|
|
439
|
+
if (typeof script !== 'string' || script.length < 10) return false;
|
|
440
|
+
// New runtime wrapper pattern
|
|
441
|
+
if (script.includes('agent-runtime') && script.includes('import')) return true;
|
|
442
|
+
// Legacy standalone pattern
|
|
443
|
+
return script.includes('process.argv') || script.includes('import ');
|
|
479
444
|
}
|
|
480
445
|
|
|
481
446
|
static _checkReferences(refContent) {
|
|
@@ -489,7 +454,9 @@ export class AutonomousResearcher {
|
|
|
489
454
|
}
|
|
490
455
|
|
|
491
456
|
static _checkContentLength(skill, script, reference) {
|
|
492
|
-
|
|
457
|
+
// Runtime wrapper scripts are short by design (3 lines) — check for runtime import
|
|
458
|
+
const scriptOk = script.includes('agent-runtime') || script.length >= 200;
|
|
459
|
+
return skill.length >= 200 && scriptOk && reference.length >= 100;
|
|
493
460
|
}
|
|
494
461
|
|
|
495
462
|
/**
|