Skip to content

Commit ca0933a

Browse files
authored
Merge pull request #3873 from mercedes-benz/develop
Merge `develop` into `master` for release
2 parents cf60926 + c0d1904 commit ca0933a

File tree

47 files changed

+1963
-56
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1963
-56
lines changed

github-actions/scan/README.adoc

+6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ To be able to use this action you need a SecHub project. Check the https://merce
7979
# OPTIONAL: job (pipeline) will be marked as failed if SecHub finds something
8080
# DEFAULT: true
8181
fail-job-with-findings: true
82+
83+
# OPTIONAL: The file that defines false positives.
84+
# This step is executed before the scan.
85+
# The action defineFalsePositives overwrites all previously marked false positives on SecHub side with the ones defined in this file.
86+
# You can use the SecHub client action getFalsePositives to get the current false positives and extend the returned false positive list.
87+
define-false-positives: 'sechub-false-positives.json'
8288
----
8389

8490
[IMPORTANT]

github-actions/scan/__test__/integrationtest.test.ts

+49
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { getFieldFromJson } from '../src/json-helper';
1010
import * as launcher from '../src/launcher';
1111
import { LaunchContext } from '../src/launcher';
1212
import { IntegrationTestContext } from './integrationtest/testframework';
13+
import { defineFalsePositives } from '../src/sechub-cli';
1314
jest.mock('@actions/core');
1415
jest.mock('@actions/artifact');
1516

@@ -321,6 +322,40 @@ describe('integrationtest non-generated config', () => {
321322

322323
});
323324

325+
describe('integrationtest define-false-positives generated config', () => {
326+
327+
test('codescan first red then result is green after define-false-positives is executed', async () => {
328+
329+
/* prepare */
330+
initInputMap();
331+
mockedInputMap.set(input.PARAM_INCLUDED_FOLDERS, '__test__/integrationtest/test-sources');
332+
mockedInputMap.set(input.PARAM_PROJECT_NAME, 'test-project-7');
333+
334+
/* execute */
335+
const result1 = await launcher.launch();
336+
337+
/* test */
338+
assertTrafficLight(result1, 'RED');
339+
assertLastClientExitCode(result1, 1);
340+
assertUploadDone();
341+
342+
/* prepare 2 */
343+
const defineFalsePositivesFile = createDefineFalsePositivesFile(result1);
344+
mockedInputMap.set(input.PARAM_DEFINE_FALSE_POSITIVES, defineFalsePositivesFile);
345+
346+
/* execute 2 */
347+
const result2 = await launcher.launch();
348+
349+
/* test 2 */
350+
assertLastClientExitCode(result2, 0);
351+
assertTrafficLight(result2, 'GREEN');
352+
assertUploadDone();
353+
354+
/* clean up */
355+
deleteFile(defineFalsePositivesFile);
356+
});
357+
358+
});
324359

325360
function assertActionIsMarkedAsFailed(){
326361
expect(setFailed).toHaveBeenCalledTimes(1);
@@ -376,3 +411,17 @@ function loadSpdxJsonReportAndAssertItContains(context: LaunchContext, textPart:
376411

377412
expect(spdxJson).toContain(textPart);
378413
}
414+
415+
function createDefineFalsePositivesFile(context: LaunchContext): string {
416+
const defineFalsePositivesJson = `{"apiVersion":"1.0","type":"falsePositiveDataList","jobData":[{"jobUUID":"${context.jobUUID}","findingId":1}]}`
417+
const fileName = "defineFalsePositivesFile.json";
418+
const filePath = `./${fileName}`;
419+
fs.writeFileSync(filePath, defineFalsePositivesJson);
420+
return filePath;
421+
}
422+
423+
function deleteFile(file: string) {
424+
if (fs.existsSync(file)) {
425+
fs.unlinkSync(file);
426+
}
427+
}

github-actions/scan/__test__/integrationtest/03-init_sechub_data.sh

+1
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,6 @@ createData 3 codescan red
8181
createData 4 webscan red
8282
createData 5 secretscan yellow
8383
createData 6 licensescan green
84+
createData 7 codescan red-def-fp
8485

8586
./sechub-api.sh project_set_whitelist_uris test-project-4 https://vulnerable.demo.example.com
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "executor-codescan-red-def-fp",
3+
"productIdentifier": "PDS_CODESCAN",
4+
"setup": {
5+
"baseURL": "https://localhost:8444",
6+
"credentials": {
7+
"user": "pds-inttest-techuser",
8+
"password": "pds-inttest-apitoken"
9+
},
10+
"jobParameters": [
11+
{
12+
"key": "sechub.productexecutor.pds.timetowait.nextcheck.milliseconds",
13+
"value": "500"
14+
},
15+
{
16+
"key": "sechub.productexecutor.pds.trustall.certificates",
17+
"value": "true"
18+
},
19+
{
20+
"key": "pds.mocking.disabled",
21+
"value": "true"
22+
},
23+
{
24+
"key": "pds.config.productidentifier",
25+
"value": "codescan_demo_red_def_fp"
26+
},
27+
{
28+
"key": "pds.config.use.sechub.storage",
29+
"value": "true"
30+
},
31+
{
32+
"key": "pds.config.supported.datatypes",
33+
"value": "SOURCE"
34+
}
35+
]
36+
},
37+
"executorVersion": 1,
38+
"enabled": true
39+
}

github-actions/scan/__test__/integrationtest/test-config/gha_integrationtest_pds-config.json

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
"scanType": "codeScan",
2121
"description": "This is only a fake code scan - used by integration tests. The code scan will just return one high vulnerability"
2222
},
23+
{
24+
"id": "codescan_demo_red_def_fp",
25+
"path": "./__test__/integrationtest/test-scripts/pds-codescan-demo-red-define-false-positives.sh",
26+
"scanType": "codeScan",
27+
"description": "This is only a fake code scan - used by integration tests. The code scan will just return one high vulnerability, which is used for false positives handling."
28+
},
2329
{
2430
"id": "webscan_demo_red",
2531
"path": "./__test__/integrationtest/test-scripts/pds-webscan-demo-red.sh",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"version": "2.1.0",
3+
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
4+
"runs": [
5+
{
6+
"tool": {
7+
"driver": {
8+
"name": "ESLint",
9+
"informationUri": "https://eslint.org",
10+
"rules": [
11+
{
12+
"id": "no-unused-vars",
13+
"shortDescription": {
14+
"text": "disallow unused variables"
15+
},
16+
"helpUri": "https://eslint.org/docs/rules/no-unused-vars",
17+
"properties": {
18+
"category": "Variables"
19+
}
20+
}
21+
]
22+
}
23+
},
24+
"artifacts": [
25+
{
26+
"location": {
27+
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"
28+
}
29+
}
30+
],
31+
"results": [
32+
{
33+
"level": "error",
34+
"message": {
35+
"text": "'x' is assigned a value but never used."
36+
},
37+
"locations": [
38+
{
39+
"physicalLocation": {
40+
"artifactLocation": {
41+
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js",
42+
"index": 0
43+
},
44+
"region": {
45+
"startLine": 1,
46+
"startColumn": 5
47+
}
48+
}
49+
}
50+
],
51+
"ruleId": "no-unused-vars",
52+
"ruleIndex": 0
53+
}
54+
]
55+
}
56+
]
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: MIT
3+
4+
cat "__test__/integrationtest/test-product-output/example-codescan-sarif-output-red.json" > "${PDS_JOB_RESULT_FILE}"

github-actions/scan/__test__/sechub-cli.test.ts

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: MIT
22

3-
import {extractJobUUID, getReport, scan} from '../src/sechub-cli';
3+
import {defineFalsePositives, extractJobUUID, getReport, scan} from '../src/sechub-cli';
44
import {execFileSync} from 'child_process';
55
import {sanitize} from "../src/shell-arg-sanitizer";
66

@@ -220,4 +220,47 @@ describe('getReport', function () {
220220
expect(sanitize).toBeCalledWith('json');
221221
});
222222

223+
});
224+
225+
describe('defineFalsePositives', function () {
226+
227+
it('sanitizes shell arguments', () => {
228+
/* prepare */
229+
const context: any = {
230+
clientExecutablePath: '/path/to/sechub-cli',
231+
projectName: 'project-name',
232+
defineFalsePositivesFile: '/path/to/define-false-positive-file'
233+
};
234+
(sanitize as jest.Mock).mockImplementation((arg) => {
235+
return arg;
236+
});
237+
238+
/* execute */
239+
defineFalsePositives(context);
240+
241+
/* test */
242+
expect(sanitize).toBeCalledTimes(3);
243+
expect(sanitize).toBeCalledWith('/path/to/sechub-cli');
244+
expect(sanitize).toBeCalledWith('project-name');
245+
expect(sanitize).toBeCalledWith('/path/to/define-false-positive-file');
246+
});
247+
248+
249+
it.each([null, undefined, ''])('context.lastClientExitCode is 0 when defineFalsePositivesFile is %s', (file) => {
250+
/* prepare */
251+
const context: any = {
252+
defineFalsePositivesFile: file
253+
};
254+
(sanitize as jest.Mock).mockImplementation((arg) => {
255+
return arg;
256+
});
257+
258+
/* execute */
259+
defineFalsePositives(context);
260+
261+
/* test */
262+
expect(sanitize).toBeCalledTimes(0);
263+
expect(context.lastClientExitCode).toBe(0);
264+
expect(context.defineFalsePositivesFile).toBe(file);
265+
});
223266
});

github-actions/scan/action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ inputs:
5757
description: 'Job will be marked as failed if SecHub finds something'
5858
required: false
5959
default: true
60+
define-false-positives:
61+
description: 'The file that defines false positives. This step is executed before the scan. The action defineFalsePositives overwrites all previously marked false positives on SecHub side with the ones defined in this file. You can use the SecHub client action getFalsePositives to get the current false positives and extend the returned false positive list.'
62+
required: false
6063

6164
outputs:
6265
scan-trafficlight:
@@ -115,6 +118,7 @@ runs:
115118
trust-all: ${{ inputs.trust-all }}
116119
debug: ${{ inputs.debug }}
117120
fail-job-with-findings: ${{ inputs.fail-job-with-findings }}
121+
define-false-positives: ${{ inputs.define-false-positives }}
118122
ACTIONS_RUNTIME_TOKEN: ${{ env.ACTIONS_RUNTIME_TOKEN }}
119123
ACTIONS_RUNTIME_URL: ${{ env.ACTIONS_RUNTIME_URL }}
120124
ACTIONS_CACHE_URL: ${{ env.ACTIONS_CACHE_URL }}

0 commit comments

Comments
 (0)