@fabasoad/sarif-to-slack 1.3.4 → 1.4.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/.github/workflows/release.yml +1 -1
- package/.github/workflows/security.yml +1 -0
- package/.github/workflows/send-sarif-to-slack.yml +39 -15
- package/.pre-commit-config.yaml +4 -4
- package/.tool-versions +1 -1
- package/Makefile +1 -1
- package/README.md +8 -7
- package/api-extractor.json +2 -2
- package/dist/Logger.js +40 -30
- package/dist/SarifToSlackClient.d.ts +0 -1
- package/dist/SarifToSlackClient.d.ts.map +1 -1
- package/dist/SarifToSlackClient.js +11 -8
- package/dist/globalState.d.ts +2 -0
- package/dist/globalState.d.ts.map +1 -0
- package/dist/globalState.js +2 -0
- package/dist/index.cjs +118 -81
- package/dist/index.d.ts +529 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/model/Finding.js +7 -5
- package/dist/model/FindingArray.js +1 -1
- package/dist/model/SendIf.js +1 -1
- package/dist/model/SlackMessage.js +6 -6
- package/dist/model/color/Color.d.ts.map +1 -1
- package/dist/model/color/Color.js +1 -1
- package/dist/model/color/ColorIdentification.js +5 -5
- package/dist/model/color/ColorOptions.d.ts.map +1 -1
- package/dist/processors/CodeQLProcessor.js +1 -1
- package/dist/processors/CommonProcessor.js +1 -1
- package/dist/processors/ProcessorFactory.js +1 -1
- package/dist/processors/SnykProcessor.js +2 -1
- package/dist/representations/CompactGroupByRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/CompactTotalPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactTotalPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactTotalRepresentation.js +1 -1
- package/dist/representations/Representation.js +1 -1
- package/dist/representations/RepresentationFactory.js +1 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupByRunRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNameRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/TableGroupRepresentation.d.ts +0 -1
- package/dist/representations/TableGroupRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupRepresentation.js +3 -3
- package/dist/representations/table/Cell.d.ts.map +1 -1
- package/dist/representations/table/Cell.js +1 -1
- package/dist/representations/table/Column.d.ts +0 -1
- package/dist/representations/table/Column.d.ts.map +1 -1
- package/dist/representations/table/Column.js +4 -3
- package/dist/representations/table/Row.d.ts +0 -1
- package/dist/representations/table/Row.d.ts.map +1 -1
- package/dist/representations/table/Row.js +3 -3
- package/dist/representations/table/Table.d.ts.map +1 -1
- package/dist/representations/table/Table.js +1 -1
- package/dist/system.js +5 -5
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types.d.ts +29 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -1
- package/dist/utils/Comparators.js +1 -1
- package/dist/utils/ExtendedArray.js +1 -1
- package/dist/utils/FileUtils.js +2 -2
- package/dist/utils/SarifUtils.js +1 -1
- package/dist/utils/StringUtils.js +1 -1
- package/etc/sarif-to-slack.api.md +21 -1
- package/jest.config.json +4 -4
- package/package.json +10 -9
- package/src/Logger.ts +50 -34
- package/src/SarifToSlackClient.ts +73 -68
- package/src/globalState.ts +11 -0
- package/src/index.ts +23 -12
- package/src/model/Finding.ts +36 -35
- package/src/model/FindingArray.ts +5 -5
- package/src/model/SendIf.ts +25 -25
- package/src/model/SlackMessage.ts +49 -49
- package/src/model/color/Color.ts +7 -7
- package/src/model/color/ColorIdentification.ts +77 -77
- package/src/model/color/ColorOptions.ts +1 -1
- package/src/processors/CodeQLProcessor.ts +3 -3
- package/src/processors/CommonProcessor.ts +24 -24
- package/src/processors/ProcessorFactory.ts +9 -9
- package/src/processors/SnykProcessor.ts +3 -2
- package/src/representations/CompactGroupByRepresentation.ts +20 -20
- package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunRepresentation.ts +10 -10
- package/src/representations/CompactGroupBySarifPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifRepresentation.ts +11 -11
- package/src/representations/CompactGroupByToolNamePerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNameRepresentation.ts +10 -10
- package/src/representations/CompactTotalPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactTotalPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactTotalRepresentation.ts +5 -5
- package/src/representations/Representation.ts +8 -8
- package/src/representations/RepresentationFactory.ts +32 -32
- package/src/representations/TableGroupByRunPerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupByRunPerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupByRunRepresentation.ts +5 -5
- package/src/representations/TableGroupBySarifPerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupBySarifPerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupBySarifRepresentation.ts +9 -9
- package/src/representations/TableGroupByToolNamePerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupByToolNamePerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupByToolNameRepresentation.ts +4 -4
- package/src/representations/TableGroupRepresentation.ts +32 -32
- package/src/representations/table/Cell.ts +8 -8
- package/src/representations/table/Column.ts +13 -13
- package/src/representations/table/Row.ts +17 -17
- package/src/representations/table/Table.ts +21 -21
- package/src/system.ts +5 -5
- package/src/types.ts +43 -13
- package/src/utils/Comparators.ts +6 -6
- package/src/utils/ExtendedArray.ts +1 -1
- package/src/utils/FileUtils.ts +3 -3
- package/src/utils/SarifUtils.ts +6 -6
- package/src/utils/StringUtils.ts +3 -3
- package/tests/integration/SendSarifToSlack.spec.ts +73 -67
- package/tests/representations/CompactGroupByRunPerLevelRepresentation.spec.ts +121 -0
- package/tests/representations/CompactGroupByRunPerSeverityRepresentation.spec.ts +122 -0
- package/tests/representations/CompactGroupBySarifPerLevelRepresentation.spec.ts +132 -0
- package/tests/representations/CompactGroupBySarifPerSeverityRepresentation.spec.ts +133 -0
- package/tsconfig.json +3 -4
- package/dist/sarif-to-slack.d.ts +0 -562
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import CompactGroupBySarifPerSeverityRepresentation from '../../src/representations/CompactGroupBySarifPerSeverityRepresentation';
|
|
2
|
+
import FindingArray from '../../src/model/FindingArray';
|
|
3
|
+
import type Finding from '../../src/model/Finding';
|
|
4
|
+
import { SecurityLevel, SecuritySeverity } from '../../src/types';
|
|
5
|
+
import type { RunData, SarifModel } from '../../src/types';
|
|
6
|
+
|
|
7
|
+
function mockFinding(opts: {
|
|
8
|
+
sarifPath?: string,
|
|
9
|
+
runId?: number,
|
|
10
|
+
toolName?: string,
|
|
11
|
+
level?: SecurityLevel,
|
|
12
|
+
severity?: SecuritySeverity,
|
|
13
|
+
}): Finding {
|
|
14
|
+
const finding: Finding = {
|
|
15
|
+
get sarifPath() { return opts.sarifPath ?? '/default.sarif' },
|
|
16
|
+
get runId() { return opts.runId ?? 1 },
|
|
17
|
+
get toolName() { return opts.toolName ?? 'Tool' },
|
|
18
|
+
get cvssScore() { return undefined },
|
|
19
|
+
get level() { return opts.level ?? SecurityLevel.Unknown },
|
|
20
|
+
get severity() { return opts.severity ?? SecuritySeverity.Unknown },
|
|
21
|
+
clone() { return mockFinding(opts) },
|
|
22
|
+
};
|
|
23
|
+
return finding;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function buildModel(
|
|
27
|
+
sarifFiles: string[],
|
|
28
|
+
findings: Finding[],
|
|
29
|
+
): SarifModel {
|
|
30
|
+
const arr = new FindingArray();
|
|
31
|
+
findings.forEach(f => arr.push(f));
|
|
32
|
+
return {
|
|
33
|
+
sarifFiles,
|
|
34
|
+
runs: [{ id: 1, toolName: 'Tool', run: {} as RunData['run'] }],
|
|
35
|
+
findings: arr,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('(unit): CompactGroupBySarifPerSeverityRepresentation', (): void => {
|
|
40
|
+
describe('compose()', (): void => {
|
|
41
|
+
test('should return "No vulnerabilities found" when there are no sarif files', (): void => {
|
|
42
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(buildModel([], []));
|
|
43
|
+
expect(repr.compose()).toBe('No vulnerabilities found');
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('should return group header with "No vulnerabilities found" when file has no findings', (): void => {
|
|
47
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
48
|
+
buildModel(['/path/to/results.sarif'], []),
|
|
49
|
+
);
|
|
50
|
+
expect(repr.compose()).toBe('_[File 1]_ *results.sarif*\nNo vulnerabilities found');
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('should compose single finding with correct severity label', (): void => {
|
|
54
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
55
|
+
buildModel(
|
|
56
|
+
['/path/to/grype.sarif'],
|
|
57
|
+
[mockFinding({ sarifPath: '/path/to/grype.sarif', severity: SecuritySeverity.Critical })],
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
expect(repr.compose()).toBe('_[File 1]_ *grype.sarif*\n*Critical*: 1');
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('should group and sort findings by severity descending', (): void => {
|
|
64
|
+
const sarifPath = '/scans/results.sarif';
|
|
65
|
+
const findings = [
|
|
66
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.Low }),
|
|
67
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.Critical }),
|
|
68
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.High }),
|
|
69
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.High }),
|
|
70
|
+
];
|
|
71
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
72
|
+
buildModel([sarifPath], findings),
|
|
73
|
+
);
|
|
74
|
+
expect(repr.compose()).toBe('_[File 1]_ *results.sarif*\n*Critical*: 1, *High*: 2, *Low*: 1');
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('should compose multiple sarif files with incrementing indices', (): void => {
|
|
78
|
+
const file1 = '/scans/grype-01.sarif';
|
|
79
|
+
const file2 = '/scans/grype-02.sarif';
|
|
80
|
+
const findings = [
|
|
81
|
+
mockFinding({ sarifPath: file1, severity: SecuritySeverity.High }),
|
|
82
|
+
mockFinding({ sarifPath: file2, severity: SecuritySeverity.Medium }),
|
|
83
|
+
];
|
|
84
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
85
|
+
buildModel([file1, file2], findings),
|
|
86
|
+
);
|
|
87
|
+
expect(repr.compose()).toBe(
|
|
88
|
+
'_[File 1]_ *grype-01.sarif*\n*High*: 1\n\n_[File 2]_ *grype-02.sarif*\n*Medium*: 1',
|
|
89
|
+
);
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('should show "No vulnerabilities found" for a file that has no matching findings', (): void => {
|
|
93
|
+
const file1 = '/scans/grype-01.sarif';
|
|
94
|
+
const file2 = '/scans/grype-02.sarif';
|
|
95
|
+
const findings = [mockFinding({ sarifPath: file1, severity: SecuritySeverity.Critical })];
|
|
96
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
97
|
+
buildModel([file1, file2], findings),
|
|
98
|
+
);
|
|
99
|
+
expect(repr.compose()).toBe(
|
|
100
|
+
'_[File 1]_ *grype-01.sarif*\n*Critical*: 1\n\n_[File 2]_ *grype-02.sarif*\nNo vulnerabilities found',
|
|
101
|
+
);
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('should use only basename for the group title', (): void => {
|
|
105
|
+
const sarifPath = '/very/long/path/to/nested/scan-results.sarif';
|
|
106
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
107
|
+
buildModel(
|
|
108
|
+
[sarifPath],
|
|
109
|
+
[mockFinding({ sarifPath, severity: SecuritySeverity.Medium })],
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
expect(repr.compose()).toBe('_[File 1]_ *scan-results.sarif*\n*Medium*: 1');
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('should handle all severity variants correctly', (): void => {
|
|
116
|
+
const sarifPath = '/scans/all-severities.sarif';
|
|
117
|
+
const findings = [
|
|
118
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.Critical }),
|
|
119
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.High }),
|
|
120
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.Medium }),
|
|
121
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.Low }),
|
|
122
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.None }),
|
|
123
|
+
mockFinding({ sarifPath, severity: SecuritySeverity.Unknown }),
|
|
124
|
+
];
|
|
125
|
+
const repr = new CompactGroupBySarifPerSeverityRepresentation(
|
|
126
|
+
buildModel([sarifPath], findings),
|
|
127
|
+
);
|
|
128
|
+
expect(repr.compose()).toBe(
|
|
129
|
+
'_[File 1]_ *all-severities.sarif*\n*Critical*: 1, *High*: 1, *Medium*: 1, *Low*: 1, *None*: 1, *Unknown*: 1',
|
|
130
|
+
);
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
})
|
package/tsconfig.json
CHANGED
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"allowSyntheticDefaultImports": true,
|
|
5
5
|
"alwaysStrict": true,
|
|
6
|
-
"baseUrl": ".",
|
|
7
6
|
"declaration": true,
|
|
8
7
|
"declarationDir": "dist",
|
|
9
8
|
"declarationMap": true,
|
|
10
|
-
"
|
|
11
|
-
"emitDecoratorMetadata": true,
|
|
9
|
+
"emitDecoratorMetadata": false,
|
|
12
10
|
"esModuleInterop": true,
|
|
13
11
|
"experimentalDecorators": true,
|
|
14
12
|
"forceConsistentCasingInFileNames": true,
|
|
15
13
|
"inlineSourceMap": true,
|
|
16
14
|
"lib": ["es2024"],
|
|
17
15
|
"module": "es2022",
|
|
18
|
-
"moduleResolution": "
|
|
16
|
+
"moduleResolution": "bundler",
|
|
17
|
+
"rootDir": "src",
|
|
19
18
|
"newLine": "lf",
|
|
20
19
|
"noFallthroughCasesInSwitch": true,
|
|
21
20
|
"noImplicitAny": true,
|