@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
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { promises as fs } from 'node:fs'
|
|
2
|
-
import type { Log } from 'sarif'
|
|
3
|
-
import Logger from './Logger'
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import type { Log } from 'sarif';
|
|
3
|
+
import Logger from './Logger';
|
|
4
4
|
import {
|
|
5
5
|
type RunData,
|
|
6
6
|
type SarifModel,
|
|
7
7
|
type SarifOptions,
|
|
8
8
|
type SarifToSlackClientOptions,
|
|
9
9
|
SecurityLevel,
|
|
10
|
-
SecuritySeverity
|
|
11
|
-
} from './types'
|
|
12
|
-
import { logMetadata } from './system'
|
|
13
|
-
import { extractListOfFiles } from './utils/FileUtils'
|
|
14
|
-
import { createRepresentation } from './representations/RepresentationFactory'
|
|
15
|
-
import { createFinding } from './model/Finding'
|
|
16
|
-
import { findToolComponent, findToolComponentDriver } from './utils/SarifUtils'
|
|
17
|
-
import { identifyColor } from './model/color/ColorIdentification'
|
|
18
|
-
import FindingArray from './model/FindingArray'
|
|
19
|
-
import { createSlackMessage, type SlackMessage } from './model/SlackMessage'
|
|
20
|
-
import { SendIf, sendIfLogMessage } from './model/SendIf'
|
|
10
|
+
SecuritySeverity,
|
|
11
|
+
} from './types';
|
|
12
|
+
import { logMetadata } from './system';
|
|
13
|
+
import { extractListOfFiles } from './utils/FileUtils';
|
|
14
|
+
import { createRepresentation } from './representations/RepresentationFactory';
|
|
15
|
+
import { createFinding } from './model/Finding';
|
|
16
|
+
import { findToolComponent, findToolComponentDriver } from './utils/SarifUtils';
|
|
17
|
+
import { identifyColor } from './model/color/ColorIdentification';
|
|
18
|
+
import FindingArray from './model/FindingArray';
|
|
19
|
+
import { createSlackMessage, type SlackMessage } from './model/SlackMessage';
|
|
20
|
+
import { SendIf, sendIfLogMessage } from './model/SendIf';
|
|
21
|
+
import { globalState } from './globalState';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Service to convert SARIF files to Slack messages and send them.
|
|
24
25
|
* @public
|
|
25
26
|
*/
|
|
26
27
|
export class SarifToSlackClient {
|
|
27
|
-
private readonly _logger = new Logger('SarifToSlackClient');
|
|
28
28
|
private _message?: SlackMessage;
|
|
29
29
|
private _sarifModel?: SarifModel;
|
|
30
30
|
|
|
@@ -52,8 +52,12 @@ export class SarifToSlackClient {
|
|
|
52
52
|
* @public
|
|
53
53
|
*/
|
|
54
54
|
public static async create(webhookUrl: string, opts: SarifToSlackClientOptions): Promise<SarifToSlackClient> {
|
|
55
|
+
globalState.loggerOpts = opts.loggerOptions;
|
|
56
|
+
|
|
57
|
+
const logger = new Logger();
|
|
58
|
+
logger.trace(opts);
|
|
59
|
+
|
|
55
60
|
const instance = new SarifToSlackClient();
|
|
56
|
-
instance._logger.trace(opts);
|
|
57
61
|
instance._sendIf = opts.sendIf ?? instance._sendIf;
|
|
58
62
|
instance._sarifModel = await SarifToSlackClient.buildModel(opts.sarif);
|
|
59
63
|
instance._message = await SarifToSlackClient.initialize(webhookUrl, opts, instance._sarifModel);
|
|
@@ -61,35 +65,35 @@ export class SarifToSlackClient {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
private static async buildModel(sarifOpts: SarifOptions): Promise<SarifModel> {
|
|
64
|
-
const sarifFiles: string[] = extractListOfFiles(sarifOpts)
|
|
68
|
+
const sarifFiles: string[] = extractListOfFiles(sarifOpts);
|
|
65
69
|
if (sarifFiles.length === 0) {
|
|
66
|
-
throw new Error(`No SARIF files found at the provided path: ${sarifOpts.path}`)
|
|
70
|
+
throw new Error(`No SARIF files found at the provided path: ${sarifOpts.path}`);
|
|
67
71
|
}
|
|
68
72
|
|
|
69
|
-
const model: SarifModel = { sarifFiles, runs: [], findings: new FindingArray() }
|
|
70
|
-
const runIdGenerator: Generator<number> = SarifToSlackClient.createRunIdGenerator()
|
|
73
|
+
const model: SarifModel = { sarifFiles, runs: [], findings: new FindingArray() };
|
|
74
|
+
const runIdGenerator: Generator<number> = SarifToSlackClient.createRunIdGenerator();
|
|
71
75
|
for (const sarifPath of sarifFiles) {
|
|
72
|
-
const sarifJson: string = await fs.readFile(sarifPath, 'utf8')
|
|
73
|
-
const sarifLog: Log = JSON.parse(sarifJson) as Log
|
|
76
|
+
const sarifJson: string = await fs.readFile(sarifPath, 'utf8');
|
|
77
|
+
const sarifLog: Log = JSON.parse(sarifJson) as Log;
|
|
74
78
|
|
|
75
79
|
for (const run of sarifLog.runs) {
|
|
76
|
-
const runId: IteratorResult<number> = runIdGenerator.next()
|
|
77
|
-
let runMetadata: RunData | undefined
|
|
80
|
+
const runId: IteratorResult<number> = runIdGenerator.next();
|
|
81
|
+
let runMetadata: RunData | undefined;
|
|
78
82
|
for (const result of run.results ?? []) {
|
|
79
83
|
runMetadata = {
|
|
80
84
|
id: runId.value,
|
|
81
85
|
run,
|
|
82
|
-
toolName: findToolComponent(run, result).name
|
|
83
|
-
}
|
|
84
|
-
model.findings.push(createFinding({ sarifPath, result, runMetadata }))
|
|
86
|
+
toolName: findToolComponent(run, result).name,
|
|
87
|
+
};
|
|
88
|
+
model.findings.push(createFinding({ sarifPath, result, runMetadata }));
|
|
85
89
|
}
|
|
86
90
|
runMetadata ??= {
|
|
87
|
-
id: runId.value, run, toolName: findToolComponentDriver(run).name
|
|
88
|
-
}
|
|
89
|
-
model.runs.push(runMetadata)
|
|
91
|
+
id: runId.value, run, toolName: findToolComponentDriver(run).name,
|
|
92
|
+
};
|
|
93
|
+
model.runs.push(runMetadata);
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
|
-
return model
|
|
96
|
+
return model;
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
/**
|
|
@@ -112,20 +116,20 @@ export class SarifToSlackClient {
|
|
|
112
116
|
iconUrl: opts.iconUrl,
|
|
113
117
|
color: identifyColor(sarifModel.findings, opts.color),
|
|
114
118
|
representation: createRepresentation(sarifModel, opts.representation),
|
|
115
|
-
})
|
|
119
|
+
});
|
|
116
120
|
if (opts.header?.include) {
|
|
117
|
-
message.withHeader(opts.header?.value)
|
|
121
|
+
message.withHeader(opts.header?.value);
|
|
118
122
|
}
|
|
119
123
|
if (opts.footer?.include) {
|
|
120
|
-
message.withFooter(opts.footer?.value, opts.footer?.type)
|
|
124
|
+
message.withFooter(opts.footer?.value, opts.footer?.type);
|
|
121
125
|
}
|
|
122
126
|
if (opts.actor?.include) {
|
|
123
|
-
message.withActor(opts.actor?.value)
|
|
127
|
+
message.withActor(opts.actor?.value);
|
|
124
128
|
}
|
|
125
129
|
if (opts.run?.include) {
|
|
126
|
-
message.withRun()
|
|
130
|
+
message.withRun();
|
|
127
131
|
}
|
|
128
|
-
return message
|
|
132
|
+
return message;
|
|
129
133
|
}
|
|
130
134
|
|
|
131
135
|
/**
|
|
@@ -136,75 +140,76 @@ export class SarifToSlackClient {
|
|
|
136
140
|
*/
|
|
137
141
|
public async send(): Promise<void> {
|
|
138
142
|
if (this._sarifModel == null) {
|
|
139
|
-
throw new Error('Could not parse SARIF file(s).')
|
|
143
|
+
throw new Error('Could not parse SARIF file(s).');
|
|
140
144
|
}
|
|
145
|
+
const logger = new Logger();
|
|
141
146
|
if (this.shouldSendMessage) {
|
|
142
147
|
if (this._message == null) {
|
|
143
|
-
throw new Error('Slack message was not prepared.')
|
|
148
|
+
throw new Error('Slack message was not prepared.');
|
|
144
149
|
}
|
|
145
|
-
const text: string = await this._message.send()
|
|
146
|
-
|
|
150
|
+
const text: string = await this._message.send();
|
|
151
|
+
logger.info('Message sent. Status:', text);
|
|
147
152
|
} else {
|
|
148
|
-
|
|
153
|
+
logger.info(sendIfLogMessage(this._sendIf));
|
|
149
154
|
}
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
private get shouldSendMessage(): boolean {
|
|
153
158
|
if (this._sendIf == null) {
|
|
154
|
-
return true
|
|
159
|
+
return true;
|
|
155
160
|
}
|
|
156
161
|
|
|
157
162
|
switch (this._sendIf) {
|
|
158
163
|
case SendIf.SeverityCritical:
|
|
159
|
-
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Critical) != null
|
|
164
|
+
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Critical) != null;
|
|
160
165
|
case SendIf.SeverityHigh:
|
|
161
|
-
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.High) != null
|
|
166
|
+
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.High) != null;
|
|
162
167
|
case SendIf.SeverityHighOrHigher:
|
|
163
|
-
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.High)
|
|
168
|
+
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.High);
|
|
164
169
|
case SendIf.SeverityMedium:
|
|
165
|
-
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Medium) != null
|
|
170
|
+
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Medium) != null;
|
|
166
171
|
case SendIf.SeverityMediumOrHigher:
|
|
167
|
-
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.Medium)
|
|
172
|
+
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.Medium);
|
|
168
173
|
case SendIf.SeverityLow:
|
|
169
|
-
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Low) != null
|
|
174
|
+
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Low) != null;
|
|
170
175
|
case SendIf.SeverityLowOrHigher:
|
|
171
|
-
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.Low)
|
|
176
|
+
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.Low);
|
|
172
177
|
case SendIf.SeverityNone:
|
|
173
|
-
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.None) != null
|
|
178
|
+
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.None) != null;
|
|
174
179
|
case SendIf.SeverityNoneOrHigher:
|
|
175
|
-
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.None)
|
|
180
|
+
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.None);
|
|
176
181
|
case SendIf.SeverityUnknown:
|
|
177
|
-
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Unknown) != null
|
|
182
|
+
return this._sarifModel?.findings.findByProperty('severity', SecuritySeverity.Unknown) != null;
|
|
178
183
|
case SendIf.SeverityUnknownOrHigher:
|
|
179
|
-
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.Unknown)
|
|
184
|
+
return !!this._sarifModel?.findings.hasSeverityOrHigher(SecuritySeverity.Unknown);
|
|
180
185
|
case SendIf.LevelError:
|
|
181
|
-
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Error) != null
|
|
186
|
+
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Error) != null;
|
|
182
187
|
case SendIf.LevelWarning:
|
|
183
|
-
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Warning) != null
|
|
188
|
+
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Warning) != null;
|
|
184
189
|
case SendIf.LevelWarningOrHigher:
|
|
185
|
-
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.Warning)
|
|
190
|
+
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.Warning);
|
|
186
191
|
case SendIf.LevelNote:
|
|
187
|
-
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Note) != null
|
|
192
|
+
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Note) != null;
|
|
188
193
|
case SendIf.LevelNoteOrHigher:
|
|
189
|
-
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.Note)
|
|
194
|
+
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.Note);
|
|
190
195
|
case SendIf.LevelNone:
|
|
191
|
-
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.None) != null
|
|
196
|
+
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.None) != null;
|
|
192
197
|
case SendIf.LevelNoneOrHigher:
|
|
193
|
-
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.None)
|
|
198
|
+
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.None);
|
|
194
199
|
case SendIf.LevelUnknown:
|
|
195
|
-
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Unknown) != null
|
|
200
|
+
return this._sarifModel?.findings.findByProperty('level', SecurityLevel.Unknown) != null;
|
|
196
201
|
case SendIf.LevelUnknownOrHigher:
|
|
197
|
-
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.Unknown)
|
|
202
|
+
return !!this._sarifModel?.findings.hasLevelOrHigher(SecurityLevel.Unknown);
|
|
198
203
|
case SendIf.Always:
|
|
199
|
-
return true
|
|
204
|
+
return true;
|
|
200
205
|
case SendIf.Some:
|
|
201
|
-
return (this._sarifModel?.findings.length ?? 0) > 0
|
|
206
|
+
return (this._sarifModel?.findings.length ?? 0) > 0;
|
|
202
207
|
case SendIf.Empty:
|
|
203
|
-
return (this._sarifModel?.findings.length ?? 0) === 0
|
|
208
|
+
return (this._sarifModel?.findings.length ?? 0) === 0;
|
|
204
209
|
case SendIf.Never:
|
|
205
|
-
return false
|
|
210
|
+
return false;
|
|
206
211
|
default:
|
|
207
|
-
throw new Error(`Unknown sendIf parameter: ${this._sendIf}`)
|
|
212
|
+
throw new Error(`Unknown sendIf parameter: ${this._sendIf}`);
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
215
|
}
|
package/src/index.ts
CHANGED
|
@@ -63,6 +63,13 @@
|
|
|
63
63
|
* },
|
|
64
64
|
* representation: RepresentationType.CompactGroupByToolNamePerSeverity,
|
|
65
65
|
* sendIf: SendIf.MediumOrHigher,
|
|
66
|
+
* loggerOptions: {
|
|
67
|
+
* logFunctionName: false,
|
|
68
|
+
* minLevel: 'debug',
|
|
69
|
+
* name: 'my-app',
|
|
70
|
+
* stylePrettyLogs: true,
|
|
71
|
+
* prettyLogTemplate: '[{{logLevelName}}] [{{name}}] {{dateIsoStr}} ',
|
|
72
|
+
* },
|
|
66
73
|
* });
|
|
67
74
|
* await client.send();
|
|
68
75
|
* ```
|
|
@@ -71,22 +78,26 @@
|
|
|
71
78
|
*
|
|
72
79
|
* @packageDocumentation
|
|
73
80
|
*/
|
|
74
|
-
export { Color } from './model/color/Color'
|
|
75
|
-
export {
|
|
81
|
+
export { Color } from './model/color/Color';
|
|
82
|
+
export type {
|
|
76
83
|
ColorOptions,
|
|
77
84
|
ColorGroupCommon,
|
|
78
85
|
ColorGroupByLevel,
|
|
79
86
|
ColorGroupBySeverity
|
|
80
|
-
} from './model/color/ColorOptions'
|
|
81
|
-
export { SendIf } from './model/SendIf'
|
|
82
|
-
export { SarifToSlackClient } from './SarifToSlackClient'
|
|
87
|
+
} from './model/color/ColorOptions';
|
|
88
|
+
export { SendIf } from './model/SendIf';
|
|
89
|
+
export { SarifToSlackClient } from './SarifToSlackClient';
|
|
83
90
|
export {
|
|
84
|
-
FooterOptions,
|
|
91
|
+
type FooterOptions,
|
|
92
|
+
type IncludeAwareOptions,
|
|
93
|
+
type IncludeAwareWithValueOptions,
|
|
94
|
+
type LogLevel,
|
|
95
|
+
type LoggerOptions,
|
|
96
|
+
type SarifFileExtension,
|
|
97
|
+
type SarifOptions,
|
|
98
|
+
type SarifToSlackClientOptions,
|
|
85
99
|
FooterType,
|
|
86
|
-
|
|
87
|
-
IncludeAwareWithValueOptions,
|
|
100
|
+
LogLevelItems,
|
|
88
101
|
RepresentationType,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
SarifToSlackClientOptions
|
|
92
|
-
} from './types'
|
|
102
|
+
SarifFileExtensionItems,
|
|
103
|
+
} from './types';
|
package/src/model/Finding.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ReportingDescriptor, Result } from 'sarif'
|
|
2
|
-
import { type RunData, SecurityLevel, SecuritySeverity } from '../types'
|
|
3
|
-
import Logger from '../Logger'
|
|
4
|
-
import type { CommonProcessor } from '../processors/CommonProcessor'
|
|
5
|
-
import { createProcessor } from '../processors/ProcessorFactory'
|
|
1
|
+
import type { ReportingDescriptor, Result } from 'sarif';
|
|
2
|
+
import { type RunData, SecurityLevel, SecuritySeverity } from '../types';
|
|
3
|
+
import Logger from '../Logger';
|
|
4
|
+
import type { CommonProcessor } from '../processors/CommonProcessor';
|
|
5
|
+
import { createProcessor } from '../processors/ProcessorFactory';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Parameters that are needed for the new {@link Finding} instance creation.
|
|
@@ -33,7 +33,7 @@ export default interface Finding {
|
|
|
33
33
|
* @internal
|
|
34
34
|
*/
|
|
35
35
|
export function createFinding(opts: FindingOptions): Finding {
|
|
36
|
-
return new FindingImpl(opts)
|
|
36
|
+
return new FindingImpl(opts);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -43,7 +43,6 @@ export function createFinding(opts: FindingOptions): Finding {
|
|
|
43
43
|
* @private
|
|
44
44
|
*/
|
|
45
45
|
class FindingImpl implements Finding {
|
|
46
|
-
private readonly _logger = new Logger('FindingImpl');
|
|
47
46
|
private readonly _runMetadata: RunData;
|
|
48
47
|
private readonly _result: Result;
|
|
49
48
|
private readonly _sarifPath: string;
|
|
@@ -57,82 +56,84 @@ class FindingImpl implements Finding {
|
|
|
57
56
|
private _levelCache: Result.level | undefined = undefined;
|
|
58
57
|
|
|
59
58
|
constructor(opts: FindingOptions) {
|
|
60
|
-
this._processor = createProcessor(opts.runMetadata.run, opts.result)
|
|
61
|
-
this._sarifPath = opts.sarifPath
|
|
62
|
-
this._runMetadata = opts.runMetadata
|
|
63
|
-
this._result = opts.result
|
|
64
|
-
this._rule = this._processor.tryFindRule()
|
|
59
|
+
this._processor = createProcessor(opts.runMetadata.run, opts.result);
|
|
60
|
+
this._sarifPath = opts.sarifPath;
|
|
61
|
+
this._runMetadata = opts.runMetadata;
|
|
62
|
+
this._result = opts.result;
|
|
63
|
+
this._rule = this._processor.tryFindRule();
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
clone(): Finding {
|
|
68
67
|
return createFinding({
|
|
69
68
|
sarifPath: this._sarifPath,
|
|
70
69
|
runMetadata: this._runMetadata,
|
|
71
|
-
result: this._result
|
|
72
|
-
})
|
|
70
|
+
result: this._result,
|
|
71
|
+
});
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
public get sarifPath(): string {
|
|
76
|
-
return this._sarifPath
|
|
75
|
+
return this._sarifPath;
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
public get runId(): number {
|
|
80
|
-
return this._runMetadata.id
|
|
79
|
+
return this._runMetadata.id;
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
public get toolName(): string {
|
|
84
|
-
return this._processor.findToolComponent().name
|
|
83
|
+
return this._processor.findToolComponent().name;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
public get cvssScore(): number | undefined {
|
|
88
87
|
if (!this._cvssScoreCacheProcessed) {
|
|
89
|
-
this._cvssScoreCacheProcessed = true
|
|
90
|
-
this._cvssScoreCache = this._processor.tryFindCvssScore()
|
|
88
|
+
this._cvssScoreCacheProcessed = true;
|
|
89
|
+
this._cvssScoreCache = this._processor.tryFindCvssScore();
|
|
91
90
|
}
|
|
92
|
-
return this._cvssScoreCache
|
|
91
|
+
return this._cvssScoreCache;
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
public get level(): SecurityLevel {
|
|
96
95
|
if (!this._levelCacheProcessed) {
|
|
97
|
-
this._levelCacheProcessed = true
|
|
98
|
-
this._levelCache = this._processor.tryFindLevel()
|
|
96
|
+
this._levelCacheProcessed = true;
|
|
97
|
+
this._levelCache = this._processor.tryFindLevel();
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
if (this._levelCache === undefined) {
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
const logger = new Logger();;
|
|
102
|
+
logger.debug(`Unknown level of ${this._rule?.id} rule`);
|
|
103
|
+
return SecurityLevel.Unknown;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
switch (this._levelCache) {
|
|
107
|
-
case 'error': return SecurityLevel.Error
|
|
108
|
-
case 'warning': return SecurityLevel.Warning
|
|
109
|
-
case 'note': return SecurityLevel.Note
|
|
110
|
-
default: return SecurityLevel.None
|
|
107
|
+
case 'error': return SecurityLevel.Error;
|
|
108
|
+
case 'warning': return SecurityLevel.Warning;
|
|
109
|
+
case 'note': return SecurityLevel.Note;
|
|
110
|
+
default: return SecurityLevel.None;
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
public get severity(): SecuritySeverity {
|
|
115
115
|
if (this.cvssScore == null || this.cvssScore < 0 || this.cvssScore > 10) {
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
const logger = new Logger();
|
|
117
|
+
logger.debug(`Unsupported CVSS score ${this.cvssScore} in ${this._rule?.id} rule`);
|
|
118
|
+
return SecuritySeverity.Unknown;
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
if (this.cvssScore >= 9) {
|
|
121
|
-
return SecuritySeverity.Critical
|
|
122
|
+
return SecuritySeverity.Critical;
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
if (this.cvssScore >= 7) {
|
|
125
|
-
return SecuritySeverity.High
|
|
126
|
+
return SecuritySeverity.High;
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
if (this.cvssScore >= 4) {
|
|
129
|
-
return SecuritySeverity.Medium
|
|
130
|
+
return SecuritySeverity.Medium;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
if (this.cvssScore >= 0.1) {
|
|
133
|
-
return SecuritySeverity.Low
|
|
134
|
+
return SecuritySeverity.Low;
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
return SecuritySeverity.None
|
|
137
|
+
return SecuritySeverity.None;
|
|
137
138
|
}
|
|
138
139
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type Finding from './Finding'
|
|
2
|
-
import { SecurityLevel, SecuritySeverity } from '../types'
|
|
3
|
-
import ExtendedArray from '../utils/ExtendedArray'
|
|
1
|
+
import type Finding from './Finding';
|
|
2
|
+
import { SecurityLevel, SecuritySeverity } from '../types';
|
|
3
|
+
import ExtendedArray from '../utils/ExtendedArray';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* This class represents an array of {@link Finding} objects and adds additional
|
|
@@ -14,7 +14,7 @@ export default class FindingArray extends ExtendedArray<Finding> {
|
|
|
14
14
|
.values(SecuritySeverity)
|
|
15
15
|
.filter((v: string | SecuritySeverity): v is SecuritySeverity => typeof v === 'number')
|
|
16
16
|
.filter((v: SecuritySeverity): boolean => v >= severity)
|
|
17
|
-
.some((v: SecuritySeverity): boolean => this.findByProperty('severity', v) != null)
|
|
17
|
+
.some((v: SecuritySeverity): boolean => this.findByProperty('severity', v) != null);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
public hasLevelOrHigher(level: SecurityLevel): boolean {
|
|
@@ -22,6 +22,6 @@ export default class FindingArray extends ExtendedArray<Finding> {
|
|
|
22
22
|
.values(SecurityLevel)
|
|
23
23
|
.filter((v: string | SecurityLevel): v is SecurityLevel => typeof v === 'number')
|
|
24
24
|
.filter((v: SecurityLevel): boolean => v >= level)
|
|
25
|
-
.some((v: SecurityLevel): boolean => this.findByProperty('level', v) != null)
|
|
25
|
+
.some((v: SecurityLevel): boolean => this.findByProperty('level', v) != null);
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/model/SendIf.ts
CHANGED
|
@@ -122,54 +122,54 @@ export enum SendIf {
|
|
|
122
122
|
export function sendIfLogMessage(sendIf: SendIf): string {
|
|
123
123
|
switch (sendIf) {
|
|
124
124
|
case SendIf.SeverityCritical:
|
|
125
|
-
return 'No message sent: no findings with "Critical" severity.'
|
|
125
|
+
return 'No message sent: no findings with "Critical" severity.';
|
|
126
126
|
case SendIf.SeverityHigh:
|
|
127
|
-
return 'No message sent: no findings with "High" severity.'
|
|
127
|
+
return 'No message sent: no findings with "High" severity.';
|
|
128
128
|
case SendIf.SeverityHighOrHigher:
|
|
129
|
-
return 'No message sent: no findings with "High" or higher severity.'
|
|
129
|
+
return 'No message sent: no findings with "High" or higher severity.';
|
|
130
130
|
case SendIf.SeverityMedium:
|
|
131
|
-
return 'No message sent: no findings with "Medium" severity.'
|
|
131
|
+
return 'No message sent: no findings with "Medium" severity.';
|
|
132
132
|
case SendIf.SeverityMediumOrHigher:
|
|
133
|
-
return 'No message sent: no findings with "Medium" or higher severity.'
|
|
133
|
+
return 'No message sent: no findings with "Medium" or higher severity.';
|
|
134
134
|
case SendIf.SeverityLow:
|
|
135
|
-
return 'No message sent: no findings with "Low" severity.'
|
|
135
|
+
return 'No message sent: no findings with "Low" severity.';
|
|
136
136
|
case SendIf.SeverityLowOrHigher:
|
|
137
|
-
return 'No message sent: no findings with "Low" or higher severity.'
|
|
137
|
+
return 'No message sent: no findings with "Low" or higher severity.';
|
|
138
138
|
case SendIf.SeverityNone:
|
|
139
|
-
return 'No message sent: no findings with "None" severity.'
|
|
139
|
+
return 'No message sent: no findings with "None" severity.';
|
|
140
140
|
case SendIf.SeverityNoneOrHigher:
|
|
141
|
-
return 'No message sent: no findings with "None" or higher severity.'
|
|
141
|
+
return 'No message sent: no findings with "None" or higher severity.';
|
|
142
142
|
case SendIf.SeverityUnknown:
|
|
143
|
-
return 'No message sent: no findings with "Unknown" severity.'
|
|
143
|
+
return 'No message sent: no findings with "Unknown" severity.';
|
|
144
144
|
case SendIf.SeverityUnknownOrHigher:
|
|
145
|
-
return 'No message sent: no findings with "Unknown" or higher severity.'
|
|
145
|
+
return 'No message sent: no findings with "Unknown" or higher severity.';
|
|
146
146
|
case SendIf.LevelError:
|
|
147
|
-
return 'No message sent: no findings with "Error" level.'
|
|
147
|
+
return 'No message sent: no findings with "Error" level.';
|
|
148
148
|
case SendIf.LevelWarning:
|
|
149
|
-
return 'No message sent: no findings with "Warning" level.'
|
|
149
|
+
return 'No message sent: no findings with "Warning" level.';
|
|
150
150
|
case SendIf.LevelWarningOrHigher:
|
|
151
|
-
return 'No message sent: no findings with "Warning" or higher level.'
|
|
151
|
+
return 'No message sent: no findings with "Warning" or higher level.';
|
|
152
152
|
case SendIf.LevelNote:
|
|
153
|
-
return 'No message sent: no findings with "Note" level.'
|
|
153
|
+
return 'No message sent: no findings with "Note" level.';
|
|
154
154
|
case SendIf.LevelNoteOrHigher:
|
|
155
|
-
return 'No message sent: no findings with "Note" or higher level.'
|
|
155
|
+
return 'No message sent: no findings with "Note" or higher level.';
|
|
156
156
|
case SendIf.LevelNone:
|
|
157
|
-
return 'No message sent: no findings with "None" level.'
|
|
157
|
+
return 'No message sent: no findings with "None" level.';
|
|
158
158
|
case SendIf.LevelNoneOrHigher:
|
|
159
|
-
return 'No message sent: no findings with "None" or higher level.'
|
|
159
|
+
return 'No message sent: no findings with "None" or higher level.';
|
|
160
160
|
case SendIf.LevelUnknown:
|
|
161
|
-
return 'No message sent: no findings with "Unknown" level.'
|
|
161
|
+
return 'No message sent: no findings with "Unknown" level.';
|
|
162
162
|
case SendIf.LevelUnknownOrHigher:
|
|
163
|
-
return 'No message sent: no findings with "Unknown" or higher level.'
|
|
163
|
+
return 'No message sent: no findings with "Unknown" or higher level.';
|
|
164
164
|
case SendIf.Always:
|
|
165
|
-
return 'Message always sent.'
|
|
165
|
+
return 'Message always sent.';
|
|
166
166
|
case SendIf.Some:
|
|
167
|
-
return 'No message sent: findings are not found.'
|
|
167
|
+
return 'No message sent: findings are not found.';
|
|
168
168
|
case SendIf.Empty:
|
|
169
|
-
return 'No message sent: some findings are found.'
|
|
169
|
+
return 'No message sent: some findings are found.';
|
|
170
170
|
case SendIf.Never:
|
|
171
|
-
return 'No message sent: sending is disabled.'
|
|
171
|
+
return 'No message sent: sending is disabled.';
|
|
172
172
|
default:
|
|
173
|
-
return 'Unknown SendIf value.'
|
|
173
|
+
return 'Unknown SendIf value.';
|
|
174
174
|
}
|
|
175
175
|
}
|