@panguard-ai/scan-core 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/dist/__tests__/atr-engine.test.d.ts +2 -0
- package/dist/__tests__/atr-engine.test.d.ts.map +1 -0
- package/dist/__tests__/atr-engine.test.js +360 -0
- package/dist/__tests__/atr-engine.test.js.map +1 -0
- package/dist/__tests__/context-signals.test.d.ts +2 -0
- package/dist/__tests__/context-signals.test.d.ts.map +1 -0
- package/dist/__tests__/context-signals.test.js +373 -0
- package/dist/__tests__/context-signals.test.js.map +1 -0
- package/dist/__tests__/hash-utils.test.d.ts +2 -0
- package/dist/__tests__/hash-utils.test.d.ts.map +1 -0
- package/dist/__tests__/hash-utils.test.js +89 -0
- package/dist/__tests__/hash-utils.test.js.map +1 -0
- package/dist/__tests__/manifest-parser.test.d.ts +2 -0
- package/dist/__tests__/manifest-parser.test.d.ts.map +1 -0
- package/dist/__tests__/manifest-parser.test.js +246 -0
- package/dist/__tests__/manifest-parser.test.js.map +1 -0
- package/dist/__tests__/risk-scorer.test.d.ts +2 -0
- package/dist/__tests__/risk-scorer.test.d.ts.map +1 -0
- package/dist/__tests__/risk-scorer.test.js +189 -0
- package/dist/__tests__/risk-scorer.test.js.map +1 -0
- package/dist/__tests__/scanner.test.d.ts +2 -0
- package/dist/__tests__/scanner.test.d.ts.map +1 -0
- package/dist/__tests__/scanner.test.js +442 -0
- package/dist/__tests__/scanner.test.js.map +1 -0
- package/dist/atr-engine.d.ts +31 -0
- package/dist/atr-engine.d.ts.map +1 -0
- package/dist/atr-engine.js +149 -0
- package/dist/atr-engine.js.map +1 -0
- package/dist/context-signals.d.ts +33 -0
- package/dist/context-signals.d.ts.map +1 -0
- package/dist/context-signals.js +162 -0
- package/dist/context-signals.js.map +1 -0
- package/dist/hash-utils.d.ts +20 -0
- package/dist/hash-utils.d.ts.map +1 -0
- package/dist/hash-utils.js +28 -0
- package/dist/hash-utils.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/instruction-patterns.d.ts +18 -0
- package/dist/instruction-patterns.d.ts.map +1 -0
- package/dist/instruction-patterns.js +291 -0
- package/dist/instruction-patterns.js.map +1 -0
- package/dist/manifest-parser.d.ts +19 -0
- package/dist/manifest-parser.d.ts.map +1 -0
- package/dist/manifest-parser.js +73 -0
- package/dist/manifest-parser.js.map +1 -0
- package/dist/markdown-utils.d.ts +16 -0
- package/dist/markdown-utils.d.ts.map +1 -0
- package/dist/markdown-utils.js +41 -0
- package/dist/markdown-utils.js.map +1 -0
- package/dist/risk-scorer.d.ts +21 -0
- package/dist/risk-scorer.d.ts.map +1 -0
- package/dist/risk-scorer.js +63 -0
- package/dist/risk-scorer.js.map +1 -0
- package/dist/scanner.d.ts +24 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +131 -0
- package/dist/scanner.js.map +1 -0
- package/dist/secret-detection.d.ts +16 -0
- package/dist/secret-detection.d.ts.map +1 -0
- package/dist/secret-detection.js +42 -0
- package/dist/secret-detection.js.map +1 -0
- package/dist/types.d.ts +106 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { parseManifestFromString, parseSkillName } from '../manifest-parser.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// parseManifestFromString
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
describe('parseManifestFromString', () => {
|
|
8
|
+
describe('valid frontmatter', () => {
|
|
9
|
+
it('parses name and description from frontmatter', () => {
|
|
10
|
+
const content = [
|
|
11
|
+
'---',
|
|
12
|
+
'name: my-skill',
|
|
13
|
+
'description: A test skill',
|
|
14
|
+
'---',
|
|
15
|
+
'Do the thing.',
|
|
16
|
+
].join('\n');
|
|
17
|
+
const manifest = parseManifestFromString(content);
|
|
18
|
+
expect(manifest.name).toBe('my-skill');
|
|
19
|
+
expect(manifest.description).toBe('A test skill');
|
|
20
|
+
});
|
|
21
|
+
it('extracts instructions as the content after frontmatter', () => {
|
|
22
|
+
const content = [
|
|
23
|
+
'---',
|
|
24
|
+
'name: my-skill',
|
|
25
|
+
'description: A test skill',
|
|
26
|
+
'---',
|
|
27
|
+
'Do the thing.',
|
|
28
|
+
'Second line.',
|
|
29
|
+
].join('\n');
|
|
30
|
+
const manifest = parseManifestFromString(content);
|
|
31
|
+
expect(manifest.instructions).toContain('Do the thing.');
|
|
32
|
+
expect(manifest.instructions).toContain('Second line.');
|
|
33
|
+
});
|
|
34
|
+
it('parses optional license field', () => {
|
|
35
|
+
const content = [
|
|
36
|
+
'---',
|
|
37
|
+
'name: my-skill',
|
|
38
|
+
'description: desc',
|
|
39
|
+
'license: MIT',
|
|
40
|
+
'---',
|
|
41
|
+
'instructions',
|
|
42
|
+
].join('\n');
|
|
43
|
+
const manifest = parseManifestFromString(content);
|
|
44
|
+
expect(manifest.license).toBe('MIT');
|
|
45
|
+
});
|
|
46
|
+
it('parses optional homepage field', () => {
|
|
47
|
+
const content = [
|
|
48
|
+
'---',
|
|
49
|
+
'name: my-skill',
|
|
50
|
+
'description: desc',
|
|
51
|
+
'homepage: https://example.com',
|
|
52
|
+
'---',
|
|
53
|
+
'instructions',
|
|
54
|
+
].join('\n');
|
|
55
|
+
const manifest = parseManifestFromString(content);
|
|
56
|
+
expect(manifest.homepage).toBe('https://example.com');
|
|
57
|
+
});
|
|
58
|
+
it('parses user-invocable boolean', () => {
|
|
59
|
+
const content = [
|
|
60
|
+
'---',
|
|
61
|
+
'name: my-skill',
|
|
62
|
+
'description: desc',
|
|
63
|
+
'user-invocable: true',
|
|
64
|
+
'---',
|
|
65
|
+
'instructions',
|
|
66
|
+
].join('\n');
|
|
67
|
+
const manifest = parseManifestFromString(content);
|
|
68
|
+
expect(manifest.userInvocable).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
it('parses allowed-tools list', () => {
|
|
71
|
+
const content = [
|
|
72
|
+
'---',
|
|
73
|
+
'name: my-skill',
|
|
74
|
+
'description: desc',
|
|
75
|
+
'allowed-tools:',
|
|
76
|
+
' - Bash',
|
|
77
|
+
' - Read',
|
|
78
|
+
'---',
|
|
79
|
+
'instructions',
|
|
80
|
+
].join('\n');
|
|
81
|
+
const manifest = parseManifestFromString(content);
|
|
82
|
+
expect(manifest['allowed-tools']).toEqual(['Bash', 'Read']);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('metadata extraction', () => {
|
|
86
|
+
it('extracts version from metadata object', () => {
|
|
87
|
+
const content = [
|
|
88
|
+
'---',
|
|
89
|
+
'name: my-skill',
|
|
90
|
+
'description: desc',
|
|
91
|
+
'metadata:',
|
|
92
|
+
' version: "1.2.3"',
|
|
93
|
+
'---',
|
|
94
|
+
'instructions',
|
|
95
|
+
].join('\n');
|
|
96
|
+
const manifest = parseManifestFromString(content);
|
|
97
|
+
expect(manifest.metadata?.version).toBe('1.2.3');
|
|
98
|
+
});
|
|
99
|
+
it('extracts tags from metadata object', () => {
|
|
100
|
+
const content = [
|
|
101
|
+
'---',
|
|
102
|
+
'name: my-skill',
|
|
103
|
+
'description: desc',
|
|
104
|
+
'metadata:',
|
|
105
|
+
' tags:',
|
|
106
|
+
' - security',
|
|
107
|
+
' - ai',
|
|
108
|
+
'---',
|
|
109
|
+
'instructions',
|
|
110
|
+
].join('\n');
|
|
111
|
+
const manifest = parseManifestFromString(content);
|
|
112
|
+
expect(manifest.metadata?.tags).toEqual(['security', 'ai']);
|
|
113
|
+
});
|
|
114
|
+
it('parses metadata when provided as a JSON string', () => {
|
|
115
|
+
const metaJson = JSON.stringify({ version: '2.0.0', tags: ['test'] });
|
|
116
|
+
const content = [
|
|
117
|
+
'---',
|
|
118
|
+
'name: my-skill',
|
|
119
|
+
'description: desc',
|
|
120
|
+
`metadata: '${metaJson}'`,
|
|
121
|
+
'---',
|
|
122
|
+
'instructions',
|
|
123
|
+
].join('\n');
|
|
124
|
+
const manifest = parseManifestFromString(content);
|
|
125
|
+
expect(manifest.metadata?.version).toBe('2.0.0');
|
|
126
|
+
});
|
|
127
|
+
it('silently ignores invalid JSON string in metadata', () => {
|
|
128
|
+
const content = [
|
|
129
|
+
'---',
|
|
130
|
+
'name: my-skill',
|
|
131
|
+
'description: desc',
|
|
132
|
+
'metadata: "not valid json {"',
|
|
133
|
+
'---',
|
|
134
|
+
'instructions',
|
|
135
|
+
].join('\n');
|
|
136
|
+
const manifest = parseManifestFromString(content);
|
|
137
|
+
expect(manifest.metadata).toBeUndefined();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('no frontmatter', () => {
|
|
141
|
+
it('treats entire content as instructions when no frontmatter present', () => {
|
|
142
|
+
const content = 'Just raw instructions without any frontmatter.';
|
|
143
|
+
const manifest = parseManifestFromString(content);
|
|
144
|
+
expect(manifest.instructions).toBe(content);
|
|
145
|
+
});
|
|
146
|
+
it('uses fallbackName when no frontmatter', () => {
|
|
147
|
+
const content = 'Raw instructions.';
|
|
148
|
+
const manifest = parseManifestFromString(content, 'fallback-name');
|
|
149
|
+
expect(manifest.name).toBe('fallback-name');
|
|
150
|
+
});
|
|
151
|
+
it('uses "unknown" as default fallback name', () => {
|
|
152
|
+
const content = 'Raw instructions.';
|
|
153
|
+
const manifest = parseManifestFromString(content);
|
|
154
|
+
expect(manifest.name).toBe('unknown');
|
|
155
|
+
});
|
|
156
|
+
it('returns empty description when no frontmatter', () => {
|
|
157
|
+
const content = 'Raw instructions.';
|
|
158
|
+
const manifest = parseManifestFromString(content);
|
|
159
|
+
expect(manifest.description).toBe('');
|
|
160
|
+
});
|
|
161
|
+
it('handles empty string content', () => {
|
|
162
|
+
const manifest = parseManifestFromString('');
|
|
163
|
+
expect(manifest.name).toBe('unknown');
|
|
164
|
+
expect(manifest.instructions).toBe('');
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe('invalid YAML frontmatter', () => {
|
|
168
|
+
it('returns fallback manifest for invalid YAML', () => {
|
|
169
|
+
// YAML that is structurally invalid within the frontmatter block
|
|
170
|
+
const content = [
|
|
171
|
+
'---',
|
|
172
|
+
'name: [unclosed bracket',
|
|
173
|
+
'description: test',
|
|
174
|
+
'---',
|
|
175
|
+
'instructions here',
|
|
176
|
+
].join('\n');
|
|
177
|
+
const manifest = parseManifestFromString(content, 'fallback');
|
|
178
|
+
// Should fall back gracefully - either parse successfully or use fallback
|
|
179
|
+
expect(manifest.name).toBeDefined();
|
|
180
|
+
expect(typeof manifest.name).toBe('string');
|
|
181
|
+
});
|
|
182
|
+
it('uses fallbackName on YAML parse failure', () => {
|
|
183
|
+
// Deeply malformed YAML that triggers a parse exception
|
|
184
|
+
const badYaml = 'key: :\n - invalid: : nested\n bad: [unclosed';
|
|
185
|
+
const content = `---\n${badYaml}\n---\ninstructions`;
|
|
186
|
+
const manifest = parseManifestFromString(content, 'my-fallback');
|
|
187
|
+
// Either parses or falls back - name must be a string
|
|
188
|
+
expect(typeof manifest.name).toBe('string');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe('edge cases', () => {
|
|
192
|
+
it('uses fallbackName when frontmatter has no name field', () => {
|
|
193
|
+
const content = [
|
|
194
|
+
'---',
|
|
195
|
+
'description: no name here',
|
|
196
|
+
'---',
|
|
197
|
+
'instructions',
|
|
198
|
+
].join('\n');
|
|
199
|
+
const manifest = parseManifestFromString(content, 'injected-name');
|
|
200
|
+
expect(manifest.name).toBe('injected-name');
|
|
201
|
+
});
|
|
202
|
+
it('handles frontmatter with CRLF line endings', () => {
|
|
203
|
+
const content = '---\r\nname: crlf-skill\r\ndescription: desc\r\n---\r\ninstructions';
|
|
204
|
+
const manifest = parseManifestFromString(content);
|
|
205
|
+
expect(manifest.name).toBe('crlf-skill');
|
|
206
|
+
});
|
|
207
|
+
it('instructions are empty string when nothing follows frontmatter', () => {
|
|
208
|
+
const content = ['---', 'name: my-skill', 'description: desc', '---'].join('\n');
|
|
209
|
+
const manifest = parseManifestFromString(content);
|
|
210
|
+
// instructions should be empty or whitespace - just not throw
|
|
211
|
+
expect(typeof manifest.instructions).toBe('string');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
// parseSkillName
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
describe('parseSkillName', () => {
|
|
219
|
+
it('extracts name from raw content with frontmatter', () => {
|
|
220
|
+
const content = ['---', 'name: extracted-skill', 'description: test', '---', 'body'].join('\n');
|
|
221
|
+
expect(parseSkillName(content)).toBe('extracted-skill');
|
|
222
|
+
});
|
|
223
|
+
it('returns null when no frontmatter present', () => {
|
|
224
|
+
const content = 'Just raw content without frontmatter.';
|
|
225
|
+
expect(parseSkillName(content)).toBeNull();
|
|
226
|
+
});
|
|
227
|
+
it('returns null when frontmatter has no name field', () => {
|
|
228
|
+
const content = ['---', 'description: no name', '---', 'body'].join('\n');
|
|
229
|
+
expect(parseSkillName(content)).toBeNull();
|
|
230
|
+
});
|
|
231
|
+
it('trims whitespace from the extracted name', () => {
|
|
232
|
+
const content = ['---', 'name: my-skill ', '---', 'body'].join('\n');
|
|
233
|
+
// The regex captures everything after "name: " so trailing space may or may not be trimmed
|
|
234
|
+
// The implementation does .trim() so we expect clean value
|
|
235
|
+
const name = parseSkillName(content);
|
|
236
|
+
expect(name).toBe('my-skill');
|
|
237
|
+
});
|
|
238
|
+
it('handles names with hyphens and dots', () => {
|
|
239
|
+
const content = ['---', 'name: my.complex-skill.v2', '---', 'body'].join('\n');
|
|
240
|
+
expect(parseSkillName(content)).toBe('my.complex-skill.v2');
|
|
241
|
+
});
|
|
242
|
+
it('returns null for empty string', () => {
|
|
243
|
+
expect(parseSkillName('')).toBeNull();
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
//# sourceMappingURL=manifest-parser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-parser.test.js","sourceRoot":"","sources":["../../src/__tests__/manifest-parser.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-scorer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/risk-scorer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { calculateRiskScore } from '../risk-scorer.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Helpers
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
function makeFinding(id, severity, overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id,
|
|
10
|
+
title: `Finding ${id}`,
|
|
11
|
+
description: `Description for ${id}`,
|
|
12
|
+
severity,
|
|
13
|
+
category: 'prompt-injection',
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Tests
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
describe('calculateRiskScore', () => {
|
|
21
|
+
describe('empty findings', () => {
|
|
22
|
+
it('returns score 0 and level LOW for empty array', () => {
|
|
23
|
+
const { score, level } = calculateRiskScore([]);
|
|
24
|
+
expect(score).toBe(0);
|
|
25
|
+
expect(level).toBe('LOW');
|
|
26
|
+
});
|
|
27
|
+
it('returns score 0 and level LOW when called with no arguments', () => {
|
|
28
|
+
// contextMultiplier defaults to 1.0
|
|
29
|
+
const { score, level } = calculateRiskScore([]);
|
|
30
|
+
expect(score).toBe(0);
|
|
31
|
+
expect(level).toBe('LOW');
|
|
32
|
+
});
|
|
33
|
+
it('returns score 0 with contextMultiplier applied to empty set', () => {
|
|
34
|
+
const { score } = calculateRiskScore([], 2.0);
|
|
35
|
+
expect(score).toBe(0);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('severity weights', () => {
|
|
39
|
+
it('single info finding = score 0', () => {
|
|
40
|
+
const { score, level } = calculateRiskScore([makeFinding('f1', 'info')]);
|
|
41
|
+
expect(score).toBe(0);
|
|
42
|
+
expect(level).toBe('LOW');
|
|
43
|
+
});
|
|
44
|
+
it('single low finding = score 1', () => {
|
|
45
|
+
const { score } = calculateRiskScore([makeFinding('f1', 'low')]);
|
|
46
|
+
expect(score).toBe(1);
|
|
47
|
+
});
|
|
48
|
+
it('single medium finding = score 5', () => {
|
|
49
|
+
const { score } = calculateRiskScore([makeFinding('f1', 'medium')]);
|
|
50
|
+
expect(score).toBe(5);
|
|
51
|
+
});
|
|
52
|
+
it('single high finding = score 15, level MEDIUM', () => {
|
|
53
|
+
const { score, level } = calculateRiskScore([makeFinding('f1', 'high')]);
|
|
54
|
+
expect(score).toBe(15);
|
|
55
|
+
expect(level).toBe('MEDIUM');
|
|
56
|
+
});
|
|
57
|
+
it('single critical finding with contextMultiplier 1.0 = score 25, level CRITICAL', () => {
|
|
58
|
+
// Logic: score >= 25 && hasCritical && !weakened => CRITICAL
|
|
59
|
+
const { score, level } = calculateRiskScore([makeFinding('f1', 'critical')], 1.0);
|
|
60
|
+
expect(score).toBe(25);
|
|
61
|
+
expect(level).toBe('CRITICAL');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('deduplication by finding ID', () => {
|
|
65
|
+
it('deduplicates findings with the same ID, keeping the highest severity', () => {
|
|
66
|
+
const findings = [
|
|
67
|
+
makeFinding('dup-id', 'low'),
|
|
68
|
+
makeFinding('dup-id', 'critical'),
|
|
69
|
+
makeFinding('dup-id', 'medium'),
|
|
70
|
+
];
|
|
71
|
+
const { score } = calculateRiskScore(findings);
|
|
72
|
+
// Only critical (weight 25) should count
|
|
73
|
+
expect(score).toBe(25);
|
|
74
|
+
});
|
|
75
|
+
it('deduplicates correctly when highest severity appears first', () => {
|
|
76
|
+
const findings = [
|
|
77
|
+
makeFinding('dup-id', 'critical'),
|
|
78
|
+
makeFinding('dup-id', 'low'),
|
|
79
|
+
];
|
|
80
|
+
const { score } = calculateRiskScore(findings);
|
|
81
|
+
expect(score).toBe(25);
|
|
82
|
+
});
|
|
83
|
+
it('keeps distinct IDs separate', () => {
|
|
84
|
+
const findings = [
|
|
85
|
+
makeFinding('id-a', 'critical'), // 25
|
|
86
|
+
makeFinding('id-b', 'high'), // 15
|
|
87
|
+
];
|
|
88
|
+
const { score } = calculateRiskScore(findings);
|
|
89
|
+
expect(score).toBe(40);
|
|
90
|
+
});
|
|
91
|
+
it('info duplicates do not inflate score', () => {
|
|
92
|
+
const findings = [
|
|
93
|
+
makeFinding('same', 'info'),
|
|
94
|
+
makeFinding('same', 'info'),
|
|
95
|
+
makeFinding('same', 'info'),
|
|
96
|
+
];
|
|
97
|
+
const { score } = calculateRiskScore(findings);
|
|
98
|
+
expect(score).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('contextMultiplier > 1 boosts score', () => {
|
|
102
|
+
it('multiplier 2.0 doubles the raw score', () => {
|
|
103
|
+
const findings = [makeFinding('f1', 'high')]; // raw = 15
|
|
104
|
+
const { score } = calculateRiskScore(findings, 2.0);
|
|
105
|
+
expect(score).toBe(30);
|
|
106
|
+
});
|
|
107
|
+
it('multiplier 1.5 rounds correctly', () => {
|
|
108
|
+
const findings = [makeFinding('f1', 'medium')]; // raw = 5, * 1.5 = 7.5 → rounds to 8
|
|
109
|
+
const { score } = calculateRiskScore(findings, 1.5);
|
|
110
|
+
expect(score).toBe(8);
|
|
111
|
+
});
|
|
112
|
+
it('multiplier boosts push score into CRITICAL territory', () => {
|
|
113
|
+
// 2 high findings = 30, * 2.5 = 75 >= 70 => CRITICAL
|
|
114
|
+
const findings = [makeFinding('f1', 'high'), makeFinding('f2', 'high')];
|
|
115
|
+
const { level } = calculateRiskScore(findings, 2.5);
|
|
116
|
+
expect(level).toBe('CRITICAL');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('contextMultiplier < 0.6 weakens critical override', () => {
|
|
120
|
+
it('critical finding with multiplier 0.5 yields MEDIUM (not HIGH)', () => {
|
|
121
|
+
const findings = [makeFinding('f1', 'critical')]; // raw = 25, * 0.5 = 12 (< 15 threshold for MEDIUM via score)
|
|
122
|
+
const { level } = calculateRiskScore(findings, 0.5);
|
|
123
|
+
// weakenedCriticalOverride = true (0.5 < 0.6), so critical forces MEDIUM only
|
|
124
|
+
expect(level).toBe('MEDIUM');
|
|
125
|
+
});
|
|
126
|
+
it('critical finding with multiplier exactly 0.6 still yields HIGH', () => {
|
|
127
|
+
// 0.6 is NOT < 0.6, so weakenedCriticalOverride = false
|
|
128
|
+
const findings = [makeFinding('f1', 'critical')];
|
|
129
|
+
const { level } = calculateRiskScore(findings, 0.6);
|
|
130
|
+
// score = round(25 * 0.6) = 15, hasCritical=true, not weakened
|
|
131
|
+
// 15 < 40, not >=40; hasCritical && !weakened => HIGH
|
|
132
|
+
expect(level).toBe('HIGH');
|
|
133
|
+
});
|
|
134
|
+
it('critical finding with multiplier 0.3 (below 0.6) yields MEDIUM', () => {
|
|
135
|
+
const findings = [makeFinding('f1', 'critical')];
|
|
136
|
+
const { level } = calculateRiskScore(findings, 0.3);
|
|
137
|
+
expect(level).toBe('MEDIUM');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('score cap at 100', () => {
|
|
141
|
+
it('many critical findings are capped at 100', () => {
|
|
142
|
+
const findings = Array.from({ length: 20 }, (_, i) => makeFinding(`f${i}`, 'critical'));
|
|
143
|
+
const { score } = calculateRiskScore(findings, 1.0);
|
|
144
|
+
expect(score).toBe(100);
|
|
145
|
+
});
|
|
146
|
+
it('multiplier cannot push score above 100', () => {
|
|
147
|
+
const findings = [
|
|
148
|
+
makeFinding('f1', 'critical'),
|
|
149
|
+
makeFinding('f2', 'critical'),
|
|
150
|
+
makeFinding('f3', 'critical'),
|
|
151
|
+
];
|
|
152
|
+
const { score } = calculateRiskScore(findings, 2.5);
|
|
153
|
+
expect(score).toBe(100);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe('risk level boundaries', () => {
|
|
157
|
+
it('score exactly 70 yields CRITICAL', () => {
|
|
158
|
+
// 14 high findings (no dedup because different IDs) = 14*15=210, *0.5 = 105 => cap 100... different approach
|
|
159
|
+
// Use medium findings: need score >= 70 via multiplier
|
|
160
|
+
// 14 medium findings = 70 raw => CRITICAL
|
|
161
|
+
const findings = Array.from({ length: 14 }, (_, i) => makeFinding(`f${i}`, 'medium'));
|
|
162
|
+
const { score, level } = calculateRiskScore(findings, 1.0);
|
|
163
|
+
expect(score).toBe(70);
|
|
164
|
+
expect(level).toBe('CRITICAL');
|
|
165
|
+
});
|
|
166
|
+
it('score 40 with no critical = HIGH', () => {
|
|
167
|
+
// 8 medium = 40
|
|
168
|
+
const findings = Array.from({ length: 8 }, (_, i) => makeFinding(`f${i}`, 'medium'));
|
|
169
|
+
const { score, level } = calculateRiskScore(findings, 1.0);
|
|
170
|
+
expect(score).toBe(40);
|
|
171
|
+
expect(level).toBe('HIGH');
|
|
172
|
+
});
|
|
173
|
+
it('score 15 with no critical = MEDIUM', () => {
|
|
174
|
+
// 3 medium = 15
|
|
175
|
+
const findings = Array.from({ length: 3 }, (_, i) => makeFinding(`f${i}`, 'medium'));
|
|
176
|
+
const { score, level } = calculateRiskScore(findings, 1.0);
|
|
177
|
+
expect(score).toBe(15);
|
|
178
|
+
expect(level).toBe('MEDIUM');
|
|
179
|
+
});
|
|
180
|
+
it('score below 15 with no critical = LOW', () => {
|
|
181
|
+
// 2 medium = 10
|
|
182
|
+
const findings = Array.from({ length: 2 }, (_, i) => makeFinding(`f${i}`, 'medium'));
|
|
183
|
+
const { score, level } = calculateRiskScore(findings, 1.0);
|
|
184
|
+
expect(score).toBe(10);
|
|
185
|
+
expect(level).toBe('LOW');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
//# sourceMappingURL=risk-scorer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-scorer.test.js","sourceRoot":"","sources":["../../src/__tests__/risk-scorer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scanner.test.ts"],"names":[],"mappings":""}
|