relsec 0.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/LICENSE +21 -0
- package/README.md +376 -0
- package/SECURITY.md +36 -0
- package/dist/advisories.d.ts +5 -0
- package/dist/advisories.js +111 -0
- package/dist/advisories.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +181 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.js +50 -0
- package/dist/config.js.map +1 -0
- package/dist/engine.d.ts +8 -0
- package/dist/engine.js +76 -0
- package/dist/engine.js.map +1 -0
- package/dist/interactive.d.ts +58 -0
- package/dist/interactive.js +698 -0
- package/dist/interactive.js.map +1 -0
- package/dist/inventory.d.ts +3 -0
- package/dist/inventory.js +27 -0
- package/dist/inventory.js.map +1 -0
- package/dist/ioc.d.ts +16 -0
- package/dist/ioc.js +46 -0
- package/dist/ioc.js.map +1 -0
- package/dist/manifests.d.ts +10 -0
- package/dist/manifests.js +157 -0
- package/dist/manifests.js.map +1 -0
- package/dist/osv.d.ts +13 -0
- package/dist/osv.js +82 -0
- package/dist/osv.js.map +1 -0
- package/dist/reachability.d.ts +6 -0
- package/dist/reachability.js +19 -0
- package/dist/reachability.js.map +1 -0
- package/dist/report.d.ts +4 -0
- package/dist/report.js +74 -0
- package/dist/report.js.map +1 -0
- package/dist/security-modules.d.ts +14 -0
- package/dist/security-modules.js +126 -0
- package/dist/security-modules.js.map +1 -0
- package/dist/theme.d.ts +43 -0
- package/dist/theme.js +191 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version-info.d.ts +1 -0
- package/dist/version-info.js +2 -0
- package/dist/version-info.js.map +1 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.js +74 -0
- package/dist/version.js.map +1 -0
- package/docs/RELEASE.md +41 -0
- package/package.json +64 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { listAdvisories, loadAdvisoriesFromFile } from './advisories.js';
|
|
5
|
+
import { analyzeCveRelevance } from './engine.js';
|
|
6
|
+
import { scanIocsInLogs } from './ioc.js';
|
|
7
|
+
import { importOsvAdvisories } from './osv.js';
|
|
8
|
+
import { renderJsonlReport, renderMarkdownReport, renderSarifReport } from './report.js';
|
|
9
|
+
import { startInteractive } from './interactive.js';
|
|
10
|
+
import { VERSION } from './version-info.js';
|
|
11
|
+
export async function runCli(argv) {
|
|
12
|
+
const [command, ...rest] = argv;
|
|
13
|
+
if (!command || command === 'help' || command === '--help' || command === '-h')
|
|
14
|
+
return help();
|
|
15
|
+
if (command === 'version' || command === '--version' || command === '-v')
|
|
16
|
+
return `relevant ${VERSION}`;
|
|
17
|
+
if (command === 'advisories')
|
|
18
|
+
return runAdvisories(rest);
|
|
19
|
+
if (command === 'import')
|
|
20
|
+
return runImport(rest);
|
|
21
|
+
if (command === 'cve')
|
|
22
|
+
return runCve(rest);
|
|
23
|
+
if (command === 'ioc')
|
|
24
|
+
return runIoc(rest);
|
|
25
|
+
throw new Error(`Unknown command: ${command}\n\n${help()}`);
|
|
26
|
+
}
|
|
27
|
+
async function runImport(args) {
|
|
28
|
+
const [source, ...rest] = args;
|
|
29
|
+
if (source !== 'osv')
|
|
30
|
+
throw new Error('Usage: relevant import osv --workspace . --inventory security/inventory.json --output security/osv-advisories.json');
|
|
31
|
+
const options = parseOptions(rest);
|
|
32
|
+
const output = optionOne(options.output);
|
|
33
|
+
if (!output)
|
|
34
|
+
throw new Error('Usage: relevant import osv --workspace . --inventory security/inventory.json --output security/osv-advisories.json');
|
|
35
|
+
const workspace = path.resolve(optionOne(options.workspace) ?? '.');
|
|
36
|
+
const result = await importOsvAdvisories({
|
|
37
|
+
workspace,
|
|
38
|
+
inventoryPath: optionOne(options.inventory) ? path.resolve(optionOne(options.inventory) ?? '') : undefined,
|
|
39
|
+
outputPath: path.resolve(output),
|
|
40
|
+
apiUrl: optionOne(options['api-url'])
|
|
41
|
+
});
|
|
42
|
+
return `Imported ${result.advisories.length} OSV advisories for ${result.dependencyCount} dependencies to ${result.outputPath}.`;
|
|
43
|
+
}
|
|
44
|
+
async function runCve(args) {
|
|
45
|
+
const cveId = args[0];
|
|
46
|
+
if (!cveId || cveId.startsWith('--'))
|
|
47
|
+
throw new Error('Usage: relevant cve <CVE-ID> [--workspace .] [--inventory inventory.json] [--format json|markdown]');
|
|
48
|
+
const options = parseOptions(args.slice(1));
|
|
49
|
+
const workspace = path.resolve(optionOne(options.workspace) ?? '.');
|
|
50
|
+
const result = await analyzeCveRelevance({
|
|
51
|
+
workspace,
|
|
52
|
+
cveId,
|
|
53
|
+
inventoryPath: optionOne(options.inventory) ? path.resolve(optionOne(options.inventory) ?? '') : undefined,
|
|
54
|
+
advisoryPath: optionOne(options.advisories) ? path.resolve(optionOne(options.advisories) ?? '') : undefined
|
|
55
|
+
});
|
|
56
|
+
const format = parseFormat(optionOne(options.format) ?? 'text');
|
|
57
|
+
if (format === 'json')
|
|
58
|
+
return JSON.stringify(result, null, 2);
|
|
59
|
+
if (format === 'markdown')
|
|
60
|
+
return renderMarkdownReport(result);
|
|
61
|
+
if (format === 'jsonl')
|
|
62
|
+
return renderJsonlReport(result);
|
|
63
|
+
if (format === 'sarif')
|
|
64
|
+
return renderSarifReport(result);
|
|
65
|
+
return [
|
|
66
|
+
`${result.subject}: ${result.verdict} (${result.risk})`,
|
|
67
|
+
result.summary,
|
|
68
|
+
'',
|
|
69
|
+
'Evidence:',
|
|
70
|
+
...result.evidence.map((item) => `- ${item}`),
|
|
71
|
+
'',
|
|
72
|
+
'Recommended actions:',
|
|
73
|
+
...result.recommendedActions.map((item) => `- ${item}`)
|
|
74
|
+
].join('\n');
|
|
75
|
+
}
|
|
76
|
+
async function runIoc(args) {
|
|
77
|
+
const options = parseOptions(args);
|
|
78
|
+
const indicators = optionOne(options.indicators);
|
|
79
|
+
if (!indicators)
|
|
80
|
+
throw new Error('Usage: relevant ioc --indicators indicators.txt --logs file.log [--logs another.log] [--format json]');
|
|
81
|
+
const logs = optionMany(options.logs);
|
|
82
|
+
if (!logs || logs.length === 0)
|
|
83
|
+
throw new Error('At least one --logs path is required.');
|
|
84
|
+
const result = await scanIocsInLogs({
|
|
85
|
+
indicatorsPath: path.resolve(indicators),
|
|
86
|
+
logPaths: logs.map((entry) => path.resolve(entry))
|
|
87
|
+
});
|
|
88
|
+
const format = parseFormat(optionOne(options.format) ?? 'text');
|
|
89
|
+
if (format === 'json')
|
|
90
|
+
return JSON.stringify(result, null, 2);
|
|
91
|
+
if (format === 'jsonl')
|
|
92
|
+
return [
|
|
93
|
+
JSON.stringify({ type: 'summary', totalMatches: result.totalMatches }),
|
|
94
|
+
...result.matches.map((match) => JSON.stringify({
|
|
95
|
+
type: 'ioc_match',
|
|
96
|
+
indicator: match.indicator,
|
|
97
|
+
indicatorType: match.type,
|
|
98
|
+
file: match.file,
|
|
99
|
+
line: match.line,
|
|
100
|
+
text: match.text
|
|
101
|
+
}))
|
|
102
|
+
].join('\n');
|
|
103
|
+
return [
|
|
104
|
+
`IOC matches: ${result.totalMatches}`,
|
|
105
|
+
...result.matches.map((match) => `- ${match.indicator} (${match.type}) ${match.file}:${match.line}`)
|
|
106
|
+
].join('\n');
|
|
107
|
+
}
|
|
108
|
+
async function runAdvisories(args) {
|
|
109
|
+
const options = parseOptions(args);
|
|
110
|
+
const file = optionOne(options.file);
|
|
111
|
+
const advisories = file ? await loadAdvisoriesFromFile(path.resolve(file)) : listAdvisories();
|
|
112
|
+
return JSON.stringify(advisories, null, 2);
|
|
113
|
+
}
|
|
114
|
+
function parseOptions(args) {
|
|
115
|
+
const result = {};
|
|
116
|
+
for (let i = 0; i < args.length; i++) {
|
|
117
|
+
const arg = args[i];
|
|
118
|
+
if (!arg?.startsWith('--'))
|
|
119
|
+
continue;
|
|
120
|
+
const key = arg.slice(2);
|
|
121
|
+
const value = args[i + 1];
|
|
122
|
+
if (!value || value.startsWith('--'))
|
|
123
|
+
throw new Error(`Missing value for --${key}`);
|
|
124
|
+
i++;
|
|
125
|
+
if (key === 'logs') {
|
|
126
|
+
const existing = result.logs;
|
|
127
|
+
result.logs = Array.isArray(existing) ? [...existing, value] : [value];
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
result[key] = value;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
function parseFormat(value) {
|
|
136
|
+
const format = Array.isArray(value) ? value[0] : value;
|
|
137
|
+
if (format === 'json' || format === 'markdown' || format === 'text' || format === 'jsonl' || format === 'sarif')
|
|
138
|
+
return format;
|
|
139
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
140
|
+
}
|
|
141
|
+
function optionOne(value) {
|
|
142
|
+
return Array.isArray(value) ? value[0] : value;
|
|
143
|
+
}
|
|
144
|
+
function optionMany(value) {
|
|
145
|
+
if (!value)
|
|
146
|
+
return [];
|
|
147
|
+
return Array.isArray(value) ? value : [value];
|
|
148
|
+
}
|
|
149
|
+
function help() {
|
|
150
|
+
return [
|
|
151
|
+
'relevant - prove whether security findings matter locally',
|
|
152
|
+
'',
|
|
153
|
+
'Commands:',
|
|
154
|
+
' relevant cve <CVE-ID> --workspace . --inventory security/inventory.json --format json',
|
|
155
|
+
' relevant ioc --indicators indicators.txt --logs auth.log --logs proxy.log --format json',
|
|
156
|
+
' relevant import osv --workspace . --inventory security/inventory.json --output security/osv-advisories.json',
|
|
157
|
+
' relevant advisories',
|
|
158
|
+
' relevant version',
|
|
159
|
+
' relevant start interactive command shell',
|
|
160
|
+
'',
|
|
161
|
+
'Formats: text, json, markdown, jsonl, sarif'
|
|
162
|
+
].join('\n');
|
|
163
|
+
}
|
|
164
|
+
async function main() {
|
|
165
|
+
try {
|
|
166
|
+
if (process.argv.slice(2).length === 0 && process.stdin.isTTY && process.stdout.isTTY) {
|
|
167
|
+
await startInteractive();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const output = await runCli(process.argv.slice(2));
|
|
171
|
+
process.stdout.write(output.endsWith('\n') ? output : `${output}\n`);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
process.stderr.write(`${error.message}\n`);
|
|
175
|
+
process.exitCode = 1;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const isDirect = process.argv[1] ? path.resolve(process.argv[1]) === fileURLToPath(import.meta.url) : false;
|
|
179
|
+
if (isDirect)
|
|
180
|
+
void main();
|
|
181
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAI5C,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,EAAE,CAAC;IAC9F,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,YAAY,OAAO,EAAE,CAAC;IACvG,IAAI,OAAO,KAAK,YAAY;QAAE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAc;IACrC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC/B,IAAI,MAAM,KAAK,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oHAAoH,CAAC,CAAC;IAC5J,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,oHAAoH,CAAC,CAAC;IACnJ,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC;QACvC,SAAS;QACT,aAAa,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QAC1G,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAChC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;KACtC,CAAC,CAAC;IACH,OAAO,YAAY,MAAM,CAAC,UAAU,CAAC,MAAM,uBAAuB,MAAM,CAAC,eAAe,oBAAoB,MAAM,CAAC,UAAU,GAAG,CAAC;AACnI,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAc;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;IAC5J,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC;QACvC,SAAS;QACT,KAAK;QACL,aAAa,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QAC1G,YAAY,EAAE,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;KAC5G,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC;IAChE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC/D,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO;QACL,GAAG,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,GAAG;QACvD,MAAM,CAAC,OAAO;QACd,EAAE;QACF,WAAW;QACX,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,EAAE;QACF,sBAAsB;QACtB,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;KACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAc;IAClC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,sGAAsG,CAAC,CAAC;IACzI,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACzF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QACxC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;KAC3D,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC;IAChE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO;YAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;YACtE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC9C,IAAI,EAAE,WAAW;gBACjB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,aAAa,EAAE,KAAK,CAAC,IAAI;gBACzB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CAAC;SACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO;QACL,gBAAgB,MAAM,CAAC,YAAY,EAAE;QACrC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;KACrG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAAc;IACzC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;IAC9F,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY,CAAC,IAAc;IAClC,MAAM,MAAM,GAAsC,EAAE,CAAC;IACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QACrC,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAC;QACpF,CAAC,EAAE,CAAC;QACJ,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;YAC7B,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,KAAwB;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvD,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC;IAC/H,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAC,KAAoC;IACrD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACjD,CAAC;AAED,SAAS,UAAU,CAAC,KAAoC;IACtD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,IAAI;IACX,OAAO;QACL,2DAA2D;QAC3D,EAAE;QACF,WAAW;QACX,yFAAyF;QACzF,2FAA2F;QAC3F,+GAA+G;QAC/G,uBAAuB;QACvB,oBAAoB;QACpB,4DAA4D;QAC5D,EAAE;QACF,6CAA6C;KAC9C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtF,MAAM,gBAAgB,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,KAAe,CAAC,OAAO,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5G,IAAI,QAAQ;IAAE,KAAK,IAAI,EAAE,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface RelevantConfig {
|
|
2
|
+
schemaVersion: 1;
|
|
3
|
+
workspace?: string;
|
|
4
|
+
inventory?: string;
|
|
5
|
+
indicators?: string;
|
|
6
|
+
format?: 'text' | 'json' | 'markdown';
|
|
7
|
+
profiles?: Record<string, unknown>;
|
|
8
|
+
workspaces?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export interface ValidationResult {
|
|
11
|
+
ok: boolean;
|
|
12
|
+
errors: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function migrateConfig(value: unknown): RelevantConfig;
|
|
15
|
+
export declare function validateConfig(value: unknown): ValidationResult;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function migrateConfig(value) {
|
|
2
|
+
const candidate = isRecord(value) ? value : {};
|
|
3
|
+
return {
|
|
4
|
+
schemaVersion: 1,
|
|
5
|
+
workspace: stringValue(candidate.workspace),
|
|
6
|
+
inventory: stringValue(candidate.inventory),
|
|
7
|
+
indicators: stringValue(candidate.indicators),
|
|
8
|
+
format: parseFormat(candidate.format),
|
|
9
|
+
profiles: isRecord(candidate.profiles) ? candidate.profiles : undefined,
|
|
10
|
+
workspaces: stringMap(candidate.workspaces)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function validateConfig(value) {
|
|
14
|
+
const errors = [];
|
|
15
|
+
if (!isRecord(value))
|
|
16
|
+
return { ok: false, errors: ['config must be an object'] };
|
|
17
|
+
if (value.schemaVersion !== 1)
|
|
18
|
+
errors.push('schemaVersion must be 1');
|
|
19
|
+
if (value.workspace !== undefined && typeof value.workspace !== 'string')
|
|
20
|
+
errors.push('workspace must be a string');
|
|
21
|
+
if (value.inventory !== undefined && typeof value.inventory !== 'string')
|
|
22
|
+
errors.push('inventory must be a string');
|
|
23
|
+
if (value.indicators !== undefined && typeof value.indicators !== 'string')
|
|
24
|
+
errors.push('indicators must be a string');
|
|
25
|
+
if (value.format !== undefined && value.format !== 'text' && value.format !== 'json' && value.format !== 'markdown')
|
|
26
|
+
errors.push('format must be text, json, or markdown');
|
|
27
|
+
if (value.workspaces !== undefined && stringMap(value.workspaces) === undefined)
|
|
28
|
+
errors.push('workspaces must be a string map');
|
|
29
|
+
return { ok: errors.length === 0, errors };
|
|
30
|
+
}
|
|
31
|
+
function parseFormat(value) {
|
|
32
|
+
if (value === 'text' || value === 'json' || value === 'markdown')
|
|
33
|
+
return value;
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
function stringValue(value) {
|
|
37
|
+
return typeof value === 'string' ? value : undefined;
|
|
38
|
+
}
|
|
39
|
+
function stringMap(value) {
|
|
40
|
+
if (!isRecord(value))
|
|
41
|
+
return undefined;
|
|
42
|
+
const entries = Object.entries(value);
|
|
43
|
+
if (!entries.every(([, item]) => typeof item === 'string'))
|
|
44
|
+
return undefined;
|
|
45
|
+
return Object.fromEntries(entries);
|
|
46
|
+
}
|
|
47
|
+
function isRecord(value) {
|
|
48
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RelevanceResult } from './types.js';
|
|
2
|
+
export interface AnalyzeCveInput {
|
|
3
|
+
workspace: string;
|
|
4
|
+
cveId: string;
|
|
5
|
+
inventoryPath?: string;
|
|
6
|
+
advisoryPath?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function analyzeCveRelevance(input: AnalyzeCveInput): Promise<RelevanceResult>;
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { findAdvisory, loadAdvisoriesFromFile } from './advisories.js';
|
|
3
|
+
import { loadInventory } from './inventory.js';
|
|
4
|
+
import { findDependency } from './manifests.js';
|
|
5
|
+
import { analyzeReachability } from './reachability.js';
|
|
6
|
+
import { satisfiesVulnerableRange } from './version.js';
|
|
7
|
+
export async function analyzeCveRelevance(input) {
|
|
8
|
+
const importedAdvisories = input.advisoryPath ? await loadAdvisoriesFromFile(input.advisoryPath) : [];
|
|
9
|
+
const advisory = findAdvisory(input.cveId, importedAdvisories);
|
|
10
|
+
if (!advisory) {
|
|
11
|
+
return {
|
|
12
|
+
subject: input.cveId,
|
|
13
|
+
verdict: 'unknown',
|
|
14
|
+
risk: 'unknown',
|
|
15
|
+
summary: 'No local advisory knowledge is available. Import an advisory, SBOM, or scanner finding to assess relevance.',
|
|
16
|
+
affectedComponents: [],
|
|
17
|
+
evidence: [`No local advisory record for ${input.cveId}.`],
|
|
18
|
+
recommendedActions: ['Fetch authoritative advisory details and rerun with a local advisory file.']
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const inventory = await loadInventory(input.inventoryPath);
|
|
22
|
+
const vulnerableServices = [];
|
|
23
|
+
const evidence = [];
|
|
24
|
+
for (const service of inventory.services) {
|
|
25
|
+
const dependency = await findDependency(input.workspace, service, advisory);
|
|
26
|
+
if (!dependency)
|
|
27
|
+
continue;
|
|
28
|
+
if (!satisfiesVulnerableRange(dependency.version, advisory.vulnerableRange, advisory.ecosystem))
|
|
29
|
+
continue;
|
|
30
|
+
vulnerableServices.push(service);
|
|
31
|
+
const manifestPath = path.relative(input.workspace, path.resolve(process.cwd(), dependency.manifestPath)).replaceAll('\\', '/');
|
|
32
|
+
evidence.push(`Found ${dependency.packageName} ${dependency.version} in ${manifestPath || dependency.manifestPath}.`);
|
|
33
|
+
const reachability = await analyzeReachability(input.workspace, service, advisory.vulnerableSymbols);
|
|
34
|
+
if (reachability.reachable) {
|
|
35
|
+
evidence.push(...reachability.evidence);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
evidence.push(`vulnerable symbol not referenced in ${service.path}.`);
|
|
39
|
+
}
|
|
40
|
+
if (service.exposure === 'internet') {
|
|
41
|
+
evidence.push(`${service.name} has public ingress: ${(service.ingress ?? []).join(', ') || 'internet exposed'}.`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
evidence.push(`${service.name} is ${service.exposure === 'internal' ? 'internal-only' : service.exposure}.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (vulnerableServices.length === 0) {
|
|
48
|
+
return {
|
|
49
|
+
subject: advisory.id,
|
|
50
|
+
verdict: 'not_relevant',
|
|
51
|
+
risk: 'low',
|
|
52
|
+
summary: `No vulnerable ${advisory.packageName} version was found in the supplied inventory.`,
|
|
53
|
+
affectedComponents: [],
|
|
54
|
+
evidence: [`No affected ${advisory.packageName} dependency matched ${advisory.vulnerableRange}.`],
|
|
55
|
+
recommendedActions: ['Keep dependency inventory current and rerun when new services are added.']
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const anyReachable = evidence.some((item) => item.startsWith('Reachable symbol'));
|
|
59
|
+
const anyInternet = vulnerableServices.some((service) => service.exposure === 'internet');
|
|
60
|
+
const verdict = anyReachable && anyInternet ? 'relevant' : 'not_relevant';
|
|
61
|
+
const risk = verdict === 'relevant' ? 'critical' : anyReachable ? 'medium' : 'low';
|
|
62
|
+
return {
|
|
63
|
+
subject: advisory.id,
|
|
64
|
+
verdict,
|
|
65
|
+
risk,
|
|
66
|
+
summary: verdict === 'relevant'
|
|
67
|
+
? `${advisory.title}: vulnerable package is reachable from an externally exposed service.`
|
|
68
|
+
: `${advisory.title}: vulnerable version exists, but current evidence does not show reachable exposed risk.`,
|
|
69
|
+
affectedComponents: vulnerableServices.map((service) => service.name),
|
|
70
|
+
evidence,
|
|
71
|
+
recommendedActions: verdict === 'relevant'
|
|
72
|
+
? advisory.recommendedActions
|
|
73
|
+
: ['Track as accepted risk or patch in the next maintenance window.', ...advisory.recommendedActions.slice(0, 1)]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { RelevanceResult } from './types.js';
|
|
2
|
+
declare const MODULES: readonly ["cve", "ioc", "exposure", "sbom", "secrets", "cloudtrail", "auth", "yara", "sigma", "asset", "vuln", "hunt"];
|
|
3
|
+
type InteractiveModule = typeof MODULES[number];
|
|
4
|
+
export interface InteractiveSessionOptions {
|
|
5
|
+
workspace?: string;
|
|
6
|
+
inventory?: string;
|
|
7
|
+
indicators?: string;
|
|
8
|
+
advisories?: string;
|
|
9
|
+
format?: 'text' | 'json' | 'markdown';
|
|
10
|
+
configPath?: string;
|
|
11
|
+
historyPath?: string;
|
|
12
|
+
shellRunner?: (command: string) => Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
export interface InteractiveSession {
|
|
15
|
+
workspace: string;
|
|
16
|
+
inventory?: string;
|
|
17
|
+
indicators?: string;
|
|
18
|
+
advisories?: string;
|
|
19
|
+
format: 'text' | 'json' | 'markdown';
|
|
20
|
+
configPath: string;
|
|
21
|
+
historyPath: string;
|
|
22
|
+
lastResult?: RelevanceResult;
|
|
23
|
+
lastOutput?: string;
|
|
24
|
+
module?: InteractiveModule;
|
|
25
|
+
cve?: string;
|
|
26
|
+
logs: string[];
|
|
27
|
+
logdir?: string;
|
|
28
|
+
logglob: string;
|
|
29
|
+
target?: string;
|
|
30
|
+
rule?: string;
|
|
31
|
+
sessions: Array<{
|
|
32
|
+
id: number;
|
|
33
|
+
kind: string;
|
|
34
|
+
subject: string;
|
|
35
|
+
output: string;
|
|
36
|
+
}>;
|
|
37
|
+
profiles: Record<string, SessionProfile>;
|
|
38
|
+
workspaces: Record<string, string>;
|
|
39
|
+
shouldExit: boolean;
|
|
40
|
+
shellRunner: (command: string) => Promise<string>;
|
|
41
|
+
}
|
|
42
|
+
interface SessionProfile {
|
|
43
|
+
workspace: string;
|
|
44
|
+
inventory?: string;
|
|
45
|
+
indicators?: string;
|
|
46
|
+
advisories?: string;
|
|
47
|
+
format: 'text' | 'json' | 'markdown';
|
|
48
|
+
logs: string[];
|
|
49
|
+
logdir?: string;
|
|
50
|
+
logglob: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function createInteractiveSession(options?: InteractiveSessionOptions): InteractiveSession;
|
|
53
|
+
export declare function executeInteractiveCommand(session: InteractiveSession, line: string): Promise<string>;
|
|
54
|
+
export declare function startInteractive(session?: InteractiveSession): Promise<void>;
|
|
55
|
+
export declare function recordHistory(session: InteractiveSession, line: string): Promise<void>;
|
|
56
|
+
export declare function completeInteractiveLine(session: InteractiveSession, line: string): [string[], string];
|
|
57
|
+
export declare function createCyclingCompleter(session: InteractiveSession): (line: string) => [string[], string];
|
|
58
|
+
export {};
|