Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add none as option for fail-on-severity #432

Merged
merged 25 commits into from Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Expand Up @@ -68,7 +68,7 @@ Configure this action by either inlining these options in your workflow file, or

| Option | Usage | Possible values | Default value |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------- |
| `fail-on-severity` | Defines the threshold for the level of severity. The action will fail on any pull requests that introduce vulnerabilities of the specified severity level or higher. | `low`, `moderate`, `high`, `critical` | `low` |
| `fail-on-severity` | Defines the threshold for the level of severity. The action will fail on any pull requests that introduce vulnerabilities of the specified severity level or higher. | `low`, `moderate`, `high`, `critical`, `none`+ | `low` |
| `allow-licenses`* | Contains a list of allowed licenses. The action will fail on pull requests that introduce dependencies with licenses that do not match the list. | Any [SPDX-compliant identifier(s)](https://spdx.org/licenses/) | none |
| `deny-licenses`* | Contains a list of prohibited licenses. The action will fail on pull requests that introduce dependencies with licenses that match the list. | Any [SPDX-compliant identifier(s)](https://spdx.org/licenses/) | none |
| `fail-on-scopes`† | Contains a list of strings of the build environments you want to support. The action will fail on pull requests that introduce vulnerabilities in the scopes that match the list. | `runtime`, `development`, `unknown` | `runtime` |
Expand All @@ -78,10 +78,14 @@ Configure this action by either inlining these options in your workflow file, or
| `base-ref`/`head-ref` | Provide custom git references for the git base/head when performing the comparison check. This is only used for event types other than `pull_request` and `pull_request_target`. | Any valid git ref(s) in your project | none |
| `comment-summary-in-pr` | Enable or disable reporting the review summary as a comment in the pull request. If enabled, you must give the workflow or job permission `pull-requests: write`. | `true`, `false` | `false` |

+when `fail-on-severity` is set to `none`, the action will not fail on any vulnerabilities or invalid licenses. This is useful if you want to use the action to generate a report of vulnerabilities and invalid licenses, but not fail the workflow.

*not supported for use with GitHub Enterprise Server

†will be supported with GitHub Enterprise Server 3.8



### Inline Configuration

You can pass options to the Dependency Review GitHub Action using your workflow file.
Expand Down
6 changes: 6 additions & 0 deletions __tests__/config.test.ts
Expand Up @@ -54,6 +54,12 @@ test('it reads custom configs', async () => {
expect(config.allow_licenses).toEqual(['BSD', 'GPL 2'])
})

test('it defaults to none severity', async () => {
setInput('fail-on-severity', 'none')
const config = await readConfig()
expect(config.fail_on_severity).toEqual('none')
})

test('it defaults to empty allow/deny lists ', async () => {
const config = await readConfig()

Expand Down
2 changes: 1 addition & 1 deletion action.yml
Expand Up @@ -7,7 +7,7 @@ inputs:
required: false
default: ${{ github.token }}
fail-on-severity:
description: Don't block PRs below this severity. Possible values are `low`, `moderate`, `high`, `critical`.
description: Don't block PRs below this severity. Possible values are `low`, `moderate`, `high`, `critical`, `none`.
required: false
default: 'low'
fail-on-scopes:
Expand Down
51 changes: 37 additions & 14 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

42 changes: 32 additions & 10 deletions src/main.ts
Expand Up @@ -33,8 +33,14 @@ async function run(): Promise<void> {
core.info('No Dependency Changes found. Skipping Dependency Review.')
return
}
// config.fail_on_severity
const failOnSeverityParams = config.fail_on_severity
const failOnVulnerability = config.fail_on_severity !== 'none'
let minSeverity: Severity = 'low'
if (failOnSeverityParams !== 'none') {
minSeverity = failOnSeverityParams
}

const minSeverity = config.fail_on_severity
const scopedChanges = filterChangesByScopes(config.fail_on_scopes, changes)
const filteredChanges = filterAllowedAdvisories(
config.allow_ghsas,
Expand Down Expand Up @@ -67,11 +73,15 @@ async function run(): Promise<void> {

if (config.vulnerability_check) {
summary.addChangeVulnerabilitiesToSummary(vulnerableChanges, minSeverity)
printVulnerabilitiesBlock(vulnerableChanges, minSeverity)
printVulnerabilitiesBlock(
vulnerableChanges,
minSeverity,
failOnVulnerability
)
}
if (config.license_check) {
summary.addLicensesToSummary(invalidLicenseChanges, config)
printLicensesBlock(invalidLicenseChanges)
printLicensesBlock(invalidLicenseChanges, failOnVulnerability)
}

summary.addScannedDependencies(changes)
Expand Down Expand Up @@ -102,19 +112,25 @@ async function run(): Promise<void> {

function printVulnerabilitiesBlock(
addedChanges: Changes,
minSeverity: Severity
minSeverity: Severity,
failOnVulnerability: boolean
): void {
let failed = false
let vulFound = false
core.group('Vulnerabilities', async () => {
if (addedChanges.length > 0) {
for (const change of addedChanges) {
printChangeVulnerabilities(change)
}
failed = true
vulFound = true
}

if (failed) {
core.setFailed('Dependency review detected vulnerable packages.')
if (vulFound) {
const msg = 'Dependency review detected vulnerable packages.'
if (failOnVulnerability) {
core.setFailed(msg)
} else {
core.warning(msg)
}
} else {
core.info(
`Dependency review did not detect any vulnerable packages with severity level "${minSeverity}" or higher.`
Expand All @@ -137,13 +153,19 @@ function printChangeVulnerabilities(change: Change): void {
}

function printLicensesBlock(
invalidLicenseChanges: Record<string, Changes>
invalidLicenseChanges: Record<string, Changes>,
failOnVulnerability: boolean
): void {
core.group('Licenses', async () => {
if (invalidLicenseChanges.forbidden.length > 0) {
core.info('\nThe following dependencies have incompatible licenses:')
printLicensesError(invalidLicenseChanges.forbidden)
core.setFailed('Dependency review detected incompatible licenses.')
const msg = 'Dependency review detected incompatible licenses.'
if (failOnVulnerability) {
core.setFailed(msg)
} else {
core.warning(msg)
}
}
if (invalidLicenseChanges.unresolved.length > 0) {
core.warning(
Expand Down
11 changes: 10 additions & 1 deletion src/schemas.ts
@@ -1,8 +1,16 @@
import * as z from 'zod'

export const FAIL_ON_SEVERITIES = [
'critical',
'high',
'moderate',
'low',
'none'
] as const
export const SEVERITIES = ['critical', 'high', 'moderate', 'low'] as const
export const SCOPES = ['unknown', 'runtime', 'development'] as const

export const FailOnSeveritySchema = z.enum(FAIL_ON_SEVERITIES).default('low')
export const SeveritySchema = z.enum(SEVERITIES).default('low')

export const ChangeSchema = z.object({
Expand Down Expand Up @@ -36,7 +44,7 @@ export const PullRequestSchema = z.object({

export const ConfigurationOptionsSchema = z
.object({
fail_on_severity: SeveritySchema,
fail_on_severity: FailOnSeveritySchema,
fail_on_scopes: z.array(z.enum(SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).optional(),
deny_licenses: z.array(z.string()).optional(),
Expand Down Expand Up @@ -77,5 +85,6 @@ export const ChangesSchema = z.array(ChangeSchema)
export type Change = z.infer<typeof ChangeSchema>
export type Changes = z.infer<typeof ChangesSchema>
export type ConfigurationOptions = z.infer<typeof ConfigurationOptionsSchema>
export type FailOnSeverity = z.infer<typeof FailOnSeveritySchema>
export type Severity = z.infer<typeof SeveritySchema>
export type Scope = (typeof SCOPES)[number]