Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
716b322ec9 | ||
|
|
12ae1bd550 | ||
|
|
bcb52636bd | ||
|
|
241ff73141 | ||
|
|
062b749663 | ||
|
|
4f00b72b84 | ||
|
|
602f968ea2 | ||
|
|
bd61ea0d9e | ||
|
|
2843194510 | ||
|
|
6944531f76 | ||
|
|
29cdbbed37 |
@@ -67,19 +67,19 @@ jobs:
|
|||||||
Configure this action by either using an external configuration file,
|
Configure this action by either using an external configuration file,
|
||||||
or by inlining these options in your workflow file.
|
or by inlining these options in your workflow file.
|
||||||
|
|
||||||
### Options
|
## Configuration Options
|
||||||
|
|
||||||
#### config-file
|
### config-file
|
||||||
|
|
||||||
A string representing the path to an external configuraton file. By
|
A string representing the path to an external configuraton file. By
|
||||||
default external configuration files are not used.
|
default external configuration files are not used.
|
||||||
|
|
||||||
**Possible values**: A string representing the absolute path to the
|
**Possible values**: A string representing the absolute path to the
|
||||||
configuration file.
|
configuration file.
|
||||||
|
|
||||||
**Example**: `config-file: ./.github/dependency-review-config.yml`.
|
**Example**: `config-file: ./.github/dependency-review-config.yml`.
|
||||||
|
|
||||||
#### fail-on-severity
|
### fail-on-severity
|
||||||
|
|
||||||
Configure the severity level for alerting. See "[Vulnerability Severity](https://github.com/actions/dependency-review-action#vulnerability-severity)".
|
Configure the severity level for alerting. See "[Vulnerability Severity](https://github.com/actions/dependency-review-action#vulnerability-severity)".
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ Configure the severity level for alerting. See "[Vulnerability Severity](https:/
|
|||||||
|
|
||||||
**Example**: `fail-on-severity: moderate`.
|
**Example**: `fail-on-severity: moderate`.
|
||||||
|
|
||||||
#### fail-on-scopes
|
### fail-on-scopes
|
||||||
|
|
||||||
A list of strings representing the build environments you want to
|
A list of strings representing the build environments you want to
|
||||||
support. The default value is `development, runtime`.
|
support. The default value is `development, runtime`.
|
||||||
@@ -97,13 +97,14 @@ support. The default value is `development, runtime`.
|
|||||||
**Inline example**: `fail-on-scopes: development, runtime`
|
**Inline example**: `fail-on-scopes: development, runtime`
|
||||||
|
|
||||||
**YAML example**:
|
**YAML example**:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# this prevents scanning development dependencies
|
# this prevents scanning development dependencies
|
||||||
fail-on-scopes:
|
fail-on-scopes:
|
||||||
- runtime
|
- runtime
|
||||||
```
|
```
|
||||||
|
|
||||||
#### allow-licenses
|
### allow-licenses
|
||||||
|
|
||||||
Only allow the licenses in this list. See "[Licenses](https://github.com/actions/dependency-review-action#licenses)".
|
Only allow the licenses in this list. See "[Licenses](https://github.com/actions/dependency-review-action#licenses)".
|
||||||
|
|
||||||
@@ -113,13 +114,14 @@ https://docs.github.com/en/rest/licenses.
|
|||||||
**Inline example**: `allow-licenses: BSD-3-Clause, MIT`
|
**Inline example**: `allow-licenses: BSD-3-Clause, MIT`
|
||||||
|
|
||||||
**YAML example**:
|
**YAML example**:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
allow-licenses:
|
allow-licenses:
|
||||||
- BSD-3-Clause
|
- BSD-3-Clause
|
||||||
- MIT
|
- MIT
|
||||||
```
|
```
|
||||||
|
|
||||||
#### deny-licenses
|
### deny-licenses
|
||||||
|
|
||||||
Add a custom list of licenses you want to block. See
|
Add a custom list of licenses you want to block. See
|
||||||
"[Licenses](https://github.com/actions/dependency-review-action#licenses)".
|
"[Licenses](https://github.com/actions/dependency-review-action#licenses)".
|
||||||
@@ -130,13 +132,30 @@ https://docs.github.com/en/rest/licenses.
|
|||||||
**Inline example**: `deny-licenses: LGPL-2.0, BSD-2-Clause`
|
**Inline example**: `deny-licenses: LGPL-2.0, BSD-2-Clause`
|
||||||
|
|
||||||
**YAML example**:
|
**YAML example**:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
deny-licenses:
|
deny-licenses:
|
||||||
- LGPL-2.0
|
- LGPL-2.0
|
||||||
- BSD-2-Clause
|
- BSD-2-Clause
|
||||||
```
|
```
|
||||||
|
|
||||||
#### base-ref/head-ref
|
### allow-ghsas
|
||||||
|
|
||||||
|
Add a custom list of GitHub Advisory IDs that can be skipped during detection.
|
||||||
|
|
||||||
|
**Possible values**: Any valid advisory GHSA ids.
|
||||||
|
|
||||||
|
**Inline example**: `allow-ghsas: GHSA-abcd-1234-5679, GHSA-efgh-1234-5679`
|
||||||
|
|
||||||
|
**YAML example**:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
allow-ghsas:
|
||||||
|
- GHSA-abcd-1234-5679
|
||||||
|
- GHSA-efgh-1234-5679
|
||||||
|
```
|
||||||
|
|
||||||
|
### base-ref/head-ref
|
||||||
|
|
||||||
Provide custom git references for the git base/head when performing
|
Provide custom git references for the git base/head when performing
|
||||||
the comparison. If you are using pull requests, or
|
the comparison. If you are using pull requests, or
|
||||||
@@ -146,6 +165,7 @@ this. The values need to be specified for all other event types.
|
|||||||
**Possible values**: Any valid git ref(s) in your project.
|
**Possible values**: Any valid git ref(s) in your project.
|
||||||
|
|
||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
base-ref: 8bb8a58d6a4028b6c2e314d5caaf273f57644896
|
base-ref: 8bb8a58d6a4028b6c2e314d5caaf273f57644896
|
||||||
head-ref: 69af5638bf660cf218aad5709a4c100e42a2f37b
|
head-ref: 69af5638bf660cf218aad5709a4c100e42a2f37b
|
||||||
@@ -163,18 +183,18 @@ file:
|
|||||||
- name: Dependency Review
|
- name: Dependency Review
|
||||||
uses: actions/dependency-review-action@v2
|
uses: actions/dependency-review-action@v2
|
||||||
with:
|
with:
|
||||||
config-file: "./.github/dependency-review-config.yml"
|
config-file: './.github/dependency-review-config.yml'
|
||||||
```
|
```
|
||||||
|
|
||||||
And then create the file in the path you just specified. **All of these fields are
|
And then create the file in the path you just specified. **All of these fields are
|
||||||
optional**:
|
optional**:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
fail-on-severity: "critical"
|
fail-on-severity: 'critical'
|
||||||
allow-licenses:
|
allow-licenses:
|
||||||
- "GPL-3.0"
|
- 'GPL-3.0'
|
||||||
- "BSD-3-Clause"
|
- 'BSD-3-Clause'
|
||||||
- "MIT"
|
- 'MIT'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Inline Configuration
|
### Inline Configuration
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ function clearInputs() {
|
|||||||
'FAIL-ON-SCOPES',
|
'FAIL-ON-SCOPES',
|
||||||
'ALLOW-LICENSES',
|
'ALLOW-LICENSES',
|
||||||
'DENY-LICENSES',
|
'DENY-LICENSES',
|
||||||
|
'ALLOW-GHSAS',
|
||||||
'CONFIG-FILE',
|
'CONFIG-FILE',
|
||||||
'BASE-REF',
|
'BASE-REF',
|
||||||
'HEAD-REF'
|
'HEAD-REF'
|
||||||
@@ -160,3 +161,17 @@ test('it raises an error when given invalid scope', async () => {
|
|||||||
setInput('fail-on-scopes', 'runtime, zombies')
|
setInput('fail-on-scopes', 'runtime, zombies')
|
||||||
expect(() => readConfig()).toThrow()
|
expect(() => readConfig()).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('it defaults to an empty GHSA allowlist', async () => {
|
||||||
|
const options = readConfig()
|
||||||
|
expect(options.allow_ghsas).toEqual(undefined)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('it successfully parses GHSA allowlist', async () => {
|
||||||
|
setInput('allow-ghsas', 'GHSA-abcd-1234-5679, GHSA-efgh-1234-5679')
|
||||||
|
const options = readConfig()
|
||||||
|
expect(options.allow_ghsas).toEqual([
|
||||||
|
'GHSA-abcd-1234-5679',
|
||||||
|
'GHSA-efgh-1234-5679'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import {expect, test} from '@jest/globals'
|
import {expect, test} from '@jest/globals'
|
||||||
import {Change, Changes} from '../src/schemas'
|
import {Change, Changes} from '../src/schemas'
|
||||||
import {filterChangesBySeverity, filterChangesByScopes} from '../src/filter'
|
import {
|
||||||
|
filterChangesBySeverity,
|
||||||
|
filterChangesByScopes,
|
||||||
|
filterOutAllowedAdvisories
|
||||||
|
} from '../src/filter'
|
||||||
|
|
||||||
let npmChange: Change = {
|
let npmChange: Change = {
|
||||||
manifest: 'package.json',
|
manifest: 'package.json',
|
||||||
@@ -48,6 +52,19 @@ let rubyChange: Change = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let noVulnNpmChange: Change = {
|
||||||
|
manifest: 'package.json',
|
||||||
|
change_type: 'added',
|
||||||
|
ecosystem: 'npm',
|
||||||
|
name: 'helpful',
|
||||||
|
version: '1.0.0',
|
||||||
|
package_url: 'pkg:npm/[email protected]',
|
||||||
|
license: 'MIT',
|
||||||
|
source_repository_url: 'github.com/some-repo',
|
||||||
|
scope: 'runtime',
|
||||||
|
vulnerabilities: []
|
||||||
|
}
|
||||||
|
|
||||||
test('it properly filters changes by severity', async () => {
|
test('it properly filters changes by severity', async () => {
|
||||||
const changes = [npmChange, rubyChange]
|
const changes = [npmChange, rubyChange]
|
||||||
let result = filterChangesBySeverity('high', changes)
|
let result = filterChangesBySeverity('high', changes)
|
||||||
@@ -72,3 +89,29 @@ test('it properly filters changes by scope', async () => {
|
|||||||
result = filterChangesByScopes(['runtime', 'development'], changes)
|
result = filterChangesByScopes(['runtime', 'development'], changes)
|
||||||
expect(result).toEqual([npmChange, rubyChange])
|
expect(result).toEqual([npmChange, rubyChange])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('it properly filters changes with allowed vulnerabilities', async () => {
|
||||||
|
const changes = [npmChange, rubyChange, noVulnNpmChange]
|
||||||
|
|
||||||
|
let result = filterOutAllowedAdvisories(['notrealGHSAID'], changes)
|
||||||
|
expect(result).toEqual([npmChange, rubyChange, noVulnNpmChange])
|
||||||
|
|
||||||
|
result = filterOutAllowedAdvisories(['first-random_string'], changes)
|
||||||
|
expect(result).toEqual([rubyChange, noVulnNpmChange])
|
||||||
|
|
||||||
|
result = filterOutAllowedAdvisories(
|
||||||
|
['second-random_string', 'third-random_string'],
|
||||||
|
changes
|
||||||
|
)
|
||||||
|
expect(result).toEqual([npmChange, noVulnNpmChange])
|
||||||
|
|
||||||
|
result = filterOutAllowedAdvisories(
|
||||||
|
['first-random_string', 'second-random_string', 'third-random_string'],
|
||||||
|
changes
|
||||||
|
)
|
||||||
|
expect(result).toEqual([noVulnNpmChange])
|
||||||
|
|
||||||
|
// if we have a change with multiple vulnerabilities but only one is allowed, we still should not filter out that change
|
||||||
|
result = filterOutAllowedAdvisories(['second-random_string'], changes)
|
||||||
|
expect(result).toEqual([npmChange, rubyChange, noVulnNpmChange])
|
||||||
|
})
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ inputs:
|
|||||||
deny-licenses:
|
deny-licenses:
|
||||||
description: Comma-separated list of forbidden licenses (e.g. "MIT, GPL 3.0, BSD 2 Clause")
|
description: Comma-separated list of forbidden licenses (e.g. "MIT, GPL 3.0, BSD 2 Clause")
|
||||||
required: false
|
required: false
|
||||||
|
allow-ghsas:
|
||||||
|
description: Comma-separated list of allowed Github Advisory IDs (e.g. "GHSA-abcd-1234-5679, GHSA-efgh-1234-5679")
|
||||||
|
required: false
|
||||||
runs:
|
runs:
|
||||||
using: 'node16'
|
using: 'node16'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|||||||
+34
-7
@@ -222,10 +222,12 @@ function run() {
|
|||||||
};
|
};
|
||||||
const scopes = config.fail_on_scopes;
|
const scopes = config.fail_on_scopes;
|
||||||
const scopedChanges = (0, filter_1.filterChangesByScopes)(scopes, changes);
|
const scopedChanges = (0, filter_1.filterChangesByScopes)(scopes, changes);
|
||||||
const addedChanges = (0, filter_1.filterChangesBySeverity)(minSeverity, scopedChanges).filter(change => change.change_type === 'added' &&
|
const allowedGhsas = config.allow_ghsas || [];
|
||||||
|
const filteredChanges = (0, filter_1.filterOutAllowedAdvisories)(allowedGhsas, scopedChanges);
|
||||||
|
const addedChanges = (0, filter_1.filterChangesBySeverity)(minSeverity, filteredChanges).filter(change => change.change_type === 'added' &&
|
||||||
change.vulnerabilities !== undefined &&
|
change.vulnerabilities !== undefined &&
|
||||||
change.vulnerabilities.length > 0);
|
change.vulnerabilities.length > 0);
|
||||||
const [licenseErrors, unknownLicenses] = (0, licenses_1.getDeniedLicenseChanges)(scopedChanges, licenses);
|
const [licenseErrors, unknownLicenses] = (0, licenses_1.getDeniedLicenseChanges)(filteredChanges, licenses);
|
||||||
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses);
|
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses);
|
||||||
if (addedChanges.length > 0) {
|
if (addedChanges.length > 0) {
|
||||||
for (const change of addedChanges) {
|
for (const change of addedChanges) {
|
||||||
@@ -371,6 +373,7 @@ exports.ConfigurationOptionsSchema = z
|
|||||||
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
|
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
|
||||||
allow_licenses: z.array(z.string()).default([]),
|
allow_licenses: z.array(z.string()).default([]),
|
||||||
deny_licenses: z.array(z.string()).default([]),
|
deny_licenses: z.array(z.string()).default([]),
|
||||||
|
allow_ghsas: z.array(z.string()).default([]),
|
||||||
config_file: z.string().optional().default('false'),
|
config_file: z.string().optional().default('false'),
|
||||||
base_ref: z.string(),
|
base_ref: z.string(),
|
||||||
head_ref: z.string()
|
head_ref: z.string()
|
||||||
@@ -14971,18 +14974,20 @@ function readInlineConfig() {
|
|||||||
.array(z.enum(schemas_1.SCOPES))
|
.array(z.enum(schemas_1.SCOPES))
|
||||||
.default(['runtime'])
|
.default(['runtime'])
|
||||||
.parse(parseList(getOptionalInput('fail-on-scopes')));
|
.parse(parseList(getOptionalInput('fail-on-scopes')));
|
||||||
const allow_licenses = getOptionalInput('allow-licenses');
|
const allow_licenses = parseList(getOptionalInput('allow-licenses'));
|
||||||
const deny_licenses = getOptionalInput('deny-licenses');
|
const deny_licenses = parseList(getOptionalInput('deny-licenses'));
|
||||||
if (allow_licenses !== undefined && deny_licenses !== undefined) {
|
if (allow_licenses !== undefined && deny_licenses !== undefined) {
|
||||||
throw new Error("Can't specify both allow_licenses and deny_licenses");
|
throw new Error("Can't specify both allow_licenses and deny_licenses");
|
||||||
}
|
}
|
||||||
|
const allow_ghsas = parseList(getOptionalInput('allow-ghsas'));
|
||||||
const base_ref = getOptionalInput('base-ref');
|
const base_ref = getOptionalInput('base-ref');
|
||||||
const head_ref = getOptionalInput('head-ref');
|
const head_ref = getOptionalInput('head-ref');
|
||||||
return {
|
return {
|
||||||
fail_on_severity,
|
fail_on_severity,
|
||||||
fail_on_scopes,
|
fail_on_scopes,
|
||||||
allow_licenses: parseList(allow_licenses),
|
allow_licenses,
|
||||||
deny_licenses: parseList(deny_licenses),
|
deny_licenses,
|
||||||
|
allow_ghsas,
|
||||||
base_ref,
|
base_ref,
|
||||||
head_ref
|
head_ref
|
||||||
};
|
};
|
||||||
@@ -15018,7 +15023,7 @@ exports.readConfigFile = readConfigFile;
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.filterChangesByScopes = exports.filterChangesBySeverity = void 0;
|
exports.filterOutAllowedAdvisories = exports.filterChangesByScopes = exports.filterChangesBySeverity = void 0;
|
||||||
const schemas_1 = __nccwpck_require__(1129);
|
const schemas_1 = __nccwpck_require__(1129);
|
||||||
function filterChangesBySeverity(severity, changes) {
|
function filterChangesBySeverity(severity, changes) {
|
||||||
const severityIdx = schemas_1.SEVERITIES.indexOf(severity);
|
const severityIdx = schemas_1.SEVERITIES.indexOf(severity);
|
||||||
@@ -15051,6 +15056,27 @@ function filterChangesByScopes(scopes, changes) {
|
|||||||
return filteredChanges;
|
return filteredChanges;
|
||||||
}
|
}
|
||||||
exports.filterChangesByScopes = filterChangesByScopes;
|
exports.filterChangesByScopes = filterChangesByScopes;
|
||||||
|
function filterOutAllowedAdvisories(ghsas, changes) {
|
||||||
|
const filteredChanges = changes.filter(change => {
|
||||||
|
const noAdvisories = change.vulnerabilities === undefined ||
|
||||||
|
change.vulnerabilities.length === 0;
|
||||||
|
if (noAdvisories) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let allAllowedAdvisories = true;
|
||||||
|
// if there's at least one advisory that is not allowlisted, we will keep the change
|
||||||
|
for (const vulnerability of change.vulnerabilities) {
|
||||||
|
if (!ghsas.includes(vulnerability.advisory_ghsa_id)) {
|
||||||
|
allAllowedAdvisories = false;
|
||||||
|
}
|
||||||
|
if (!allAllowedAdvisories) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filteredChanges;
|
||||||
|
}
|
||||||
|
exports.filterOutAllowedAdvisories = filterOutAllowedAdvisories;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -15120,6 +15146,7 @@ exports.ConfigurationOptionsSchema = z
|
|||||||
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
|
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
|
||||||
allow_licenses: z.array(z.string()).default([]),
|
allow_licenses: z.array(z.string()).default([]),
|
||||||
deny_licenses: z.array(z.string()).default([]),
|
deny_licenses: z.array(z.string()).default([]),
|
||||||
|
allow_ghsas: z.array(z.string()).default([]),
|
||||||
config_file: z.string().optional().default('false'),
|
config_file: z.string().optional().default('false'),
|
||||||
base_ref: z.string(),
|
base_ref: z.string(),
|
||||||
head_ref: z.string()
|
head_ref: z.string()
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "dependency-review-action",
|
"name": "dependency-review-action",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "dependency-review-action",
|
"name": "dependency-review-action",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.9.1",
|
"@actions/core": "^1.9.1",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dependency-review-action",
|
"name": "dependency-review-action",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "A GitHub Action for Dependency Review",
|
"description": "A GitHub Action for Dependency Review",
|
||||||
"main": "lib/main.js",
|
"main": "lib/main.js",
|
||||||
|
|||||||
+7
-4
@@ -47,21 +47,24 @@ export function readInlineConfig(): ConfigurationOptions {
|
|||||||
.default(['runtime'])
|
.default(['runtime'])
|
||||||
.parse(parseList(getOptionalInput('fail-on-scopes')))
|
.parse(parseList(getOptionalInput('fail-on-scopes')))
|
||||||
|
|
||||||
const allow_licenses = getOptionalInput('allow-licenses')
|
const allow_licenses = parseList(getOptionalInput('allow-licenses'))
|
||||||
const deny_licenses = getOptionalInput('deny-licenses')
|
const deny_licenses = parseList(getOptionalInput('deny-licenses'))
|
||||||
|
|
||||||
if (allow_licenses !== undefined && deny_licenses !== undefined) {
|
if (allow_licenses !== undefined && deny_licenses !== undefined) {
|
||||||
throw new Error("Can't specify both allow_licenses and deny_licenses")
|
throw new Error("Can't specify both allow_licenses and deny_licenses")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const allow_ghsas = parseList(getOptionalInput('allow-ghsas'))
|
||||||
|
|
||||||
const base_ref = getOptionalInput('base-ref')
|
const base_ref = getOptionalInput('base-ref')
|
||||||
const head_ref = getOptionalInput('head-ref')
|
const head_ref = getOptionalInput('head-ref')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fail_on_severity,
|
fail_on_severity,
|
||||||
fail_on_scopes,
|
fail_on_scopes,
|
||||||
allow_licenses: parseList(allow_licenses),
|
allow_licenses,
|
||||||
deny_licenses: parseList(deny_licenses),
|
deny_licenses,
|
||||||
|
allow_ghsas,
|
||||||
base_ref,
|
base_ref,
|
||||||
head_ref
|
head_ref
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,3 +46,31 @@ export function filterChangesByScopes(
|
|||||||
|
|
||||||
return filteredChanges
|
return filteredChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function filterOutAllowedAdvisories(
|
||||||
|
ghsas: string[],
|
||||||
|
changes: Changes
|
||||||
|
): Changes {
|
||||||
|
const filteredChanges = changes.filter(change => {
|
||||||
|
const noAdvisories =
|
||||||
|
change.vulnerabilities === undefined ||
|
||||||
|
change.vulnerabilities.length === 0
|
||||||
|
|
||||||
|
if (noAdvisories) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
let allAllowedAdvisories = true
|
||||||
|
// if there's at least one advisory that is not allowlisted, we will keep the change
|
||||||
|
for (const vulnerability of change.vulnerabilities) {
|
||||||
|
if (!ghsas.includes(vulnerability.advisory_ghsa_id)) {
|
||||||
|
allAllowedAdvisories = false
|
||||||
|
}
|
||||||
|
if (!allAllowedAdvisories) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return filteredChanges
|
||||||
|
}
|
||||||
|
|||||||
+14
-3
@@ -5,7 +5,11 @@ import styles from 'ansi-styles'
|
|||||||
import {RequestError} from '@octokit/request-error'
|
import {RequestError} from '@octokit/request-error'
|
||||||
import {Change, Severity, Scope} from './schemas'
|
import {Change, Severity, Scope} from './schemas'
|
||||||
import {readConfig} from '../src/config'
|
import {readConfig} from '../src/config'
|
||||||
import {filterChangesBySeverity, filterChangesByScopes} from '../src/filter'
|
import {
|
||||||
|
filterChangesBySeverity,
|
||||||
|
filterChangesByScopes,
|
||||||
|
filterOutAllowedAdvisories
|
||||||
|
} from '../src/filter'
|
||||||
import {getDeniedLicenseChanges} from './licenses'
|
import {getDeniedLicenseChanges} from './licenses'
|
||||||
import * as summary from './summary'
|
import * as summary from './summary'
|
||||||
import {getRefs} from './git-refs'
|
import {getRefs} from './git-refs'
|
||||||
@@ -34,9 +38,16 @@ async function run(): Promise<void> {
|
|||||||
|
|
||||||
const scopedChanges = filterChangesByScopes(scopes as Scope[], changes)
|
const scopedChanges = filterChangesByScopes(scopes as Scope[], changes)
|
||||||
|
|
||||||
|
const allowedGhsas: string[] = config.allow_ghsas || []
|
||||||
|
|
||||||
|
const filteredChanges = filterOutAllowedAdvisories(
|
||||||
|
allowedGhsas,
|
||||||
|
scopedChanges
|
||||||
|
)
|
||||||
|
|
||||||
const addedChanges = filterChangesBySeverity(
|
const addedChanges = filterChangesBySeverity(
|
||||||
minSeverity as Severity,
|
minSeverity as Severity,
|
||||||
scopedChanges
|
filteredChanges
|
||||||
).filter(
|
).filter(
|
||||||
change =>
|
change =>
|
||||||
change.change_type === 'added' &&
|
change.change_type === 'added' &&
|
||||||
@@ -45,7 +56,7 @@ async function run(): Promise<void> {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const [licenseErrors, unknownLicenses] = getDeniedLicenseChanges(
|
const [licenseErrors, unknownLicenses] = getDeniedLicenseChanges(
|
||||||
scopedChanges,
|
filteredChanges,
|
||||||
licenses
|
licenses
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const ConfigurationOptionsSchema = z
|
|||||||
fail_on_scopes: z.array(z.enum(SCOPES)).default(['runtime']),
|
fail_on_scopes: z.array(z.enum(SCOPES)).default(['runtime']),
|
||||||
allow_licenses: z.array(z.string()).default([]),
|
allow_licenses: z.array(z.string()).default([]),
|
||||||
deny_licenses: z.array(z.string()).default([]),
|
deny_licenses: z.array(z.string()).default([]),
|
||||||
|
allow_ghsas: z.array(z.string()).default([]),
|
||||||
config_file: z.string().optional().default('false'),
|
config_file: z.string().optional().default('false'),
|
||||||
base_ref: z.string(),
|
base_ref: z.string(),
|
||||||
head_ref: z.string()
|
head_ref: z.string()
|
||||||
|
|||||||
Reference in New Issue
Block a user