Skip to content

Commit

Permalink
Merge pull request #709 from jhutchings1/scorecard
Browse files Browse the repository at this point in the history
Add support for calculating OpenSSF Scorecards
  • Loading branch information
febuiles committed Mar 14, 2024
2 parents 97f7ba0 + 4ce1201 commit adaed32
Show file tree
Hide file tree
Showing 12 changed files with 696 additions and 30 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -83,6 +83,8 @@ Configure this action by either inlining these options in your workflow file, or
| `retry-on-snapshot-warnings`\* | Enable or disable retrying the action every 10 seconds while waiting for dependency submission actions to complete. | `true`, `false` | `false` |
| `retry-on-snapshot-warnings-timeout`\* | Maximum amount of time (in seconds) to retry the action while waiting for dependency submission actions to complete. | Any positive integer | 120 |
| `warn-only`+ | When set to `true`, the action will log all vulnerabilities as warnings regardless of the severity, and the action will complete with a `success` status. This overrides the `fail-on-severity` option. | `true`, `false` | `false` |
| `show-openssf-scorecard-levels` | When set to `true`, the action will output information about all the known OpenSSF Scorecard scores for the dependencies changed in this pull request. | `true`, `false` | `true` |
| `warn-on-openssf-scorecard-level` | When `show-openssf-scorecard-levels` is set to `true`, this option lets you configure the threshold for when a score is considered too low and gets a :warning: warning in the CI. | Any positive integer | 3 |

\*not supported for use with GitHub Enterprise Server

Expand Down
40 changes: 40 additions & 0 deletions __tests__/scorecard.test.ts
@@ -0,0 +1,40 @@
import {expect, test} from '@jest/globals'
import {Change, Changes} from '../src/schemas'
import {getScorecardLevels, getProjectUrl} from '../src/scorecard'

const npmChange: Change = {
manifest: 'package.json',
change_type: 'added',
ecosystem: 'npm',
name: 'type-is',
version: '1.6.18',
package_url: 'pkg:npm/type-is@1.6.18',
license: 'MIT',
source_repository_url: 'github.com/jshttp/type-is',
scope: 'runtime',
vulnerabilities: [
{
severity: 'critical',
advisory_ghsa_id: 'first-random_string',
advisory_summary: 'very dangerous',
advisory_url: 'github.com/future-funk'
}
]
}

test('Get scorecard from API', async () => {
const changes: Changes = [npmChange]
const scorecard = await getScorecardLevels(changes)
expect(scorecard).not.toBeNull()
expect(scorecard.dependencies).toHaveLength(1)
expect(scorecard.dependencies[0].scorecard?.score).toBeGreaterThan(0)
})

test('Get project URL from deps.dev API', async () => {
const result = await getProjectUrl(
npmChange.ecosystem,
npmChange.name,
npmChange.version
)
expect(result).not.toBeNull()
})
38 changes: 36 additions & 2 deletions __tests__/summary.test.ts
@@ -1,5 +1,5 @@
import {expect, jest, test} from '@jest/globals'
import {Changes, ConfigurationOptions} from '../src/schemas'
import {Changes, ConfigurationOptions, Scorecard} from '../src/schemas'
import * as summary from '../src/summary'
import * as core from '@actions/core'
import {createTestChange} from './fixtures/create-test-change'
Expand All @@ -16,6 +16,9 @@ const emptyInvalidLicenseChanges = {
unresolved: [],
unlicensed: []
}
const emptyScorecard: Scorecard = {
dependencies: []
}
const defaultConfig: ConfigurationOptions = {
vulnerability_check: true,
license_check: true,
Expand All @@ -29,7 +32,9 @@ const defaultConfig: ConfigurationOptions = {
comment_summary_in_pr: true,
retry_on_snapshot_warnings: false,
retry_on_snapshot_warnings_timeout: 120,
warn_only: false
warn_only: false,
warn_on_openssf_scorecard_level: 3,
show_openssf_scorecard: false
}

const changesWithEmptyManifests: Changes = [
Expand Down Expand Up @@ -71,11 +76,32 @@ const changesWithEmptyManifests: Changes = [
}
]

const scorecard: Scorecard = {
dependencies: [
{
change: {
change_type: 'added',
manifest: '',
ecosystem: 'unknown',
name: 'castore',
version: '0.1.17',
package_url: 'pkg:hex/castore@0.1.17',
license: null,
source_repository_url: null,
scope: 'runtime',
vulnerabilities: []
},
scorecard: null
}
]
}

test('prints headline as h1', () => {
summary.addSummaryToSummary(
emptyChanges,
emptyInvalidLicenseChanges,
emptyChanges,
scorecard,
defaultConfig
)
const text = core.summary.stringify()
Expand All @@ -88,6 +114,7 @@ test('only includes "No vulnerabilities or license issues found"-message if both
emptyChanges,
emptyInvalidLicenseChanges,
emptyChanges,
emptyScorecard,
defaultConfig
)
const text = core.summary.stringify()
Expand All @@ -101,6 +128,7 @@ test('only includes "No vulnerabilities found"-message if "license_check" is set
emptyChanges,
emptyInvalidLicenseChanges,
emptyChanges,
emptyScorecard,
config
)
const text = core.summary.stringify()
Expand All @@ -114,6 +142,7 @@ test('only includes "No license issues found"-message if "vulnerability_check" i
emptyChanges,
emptyInvalidLicenseChanges,
emptyChanges,
emptyScorecard,
config
)
const text = core.summary.stringify()
Expand All @@ -126,6 +155,7 @@ test('groups dependencies with empty manifest paths together', () => {
changesWithEmptyManifests,
emptyInvalidLicenseChanges,
emptyChanges,
emptyScorecard,
defaultConfig
)
summary.addScannedDependencies(changesWithEmptyManifests)
Expand All @@ -143,6 +173,7 @@ test('does not include status section if nothing was found', () => {
emptyChanges,
emptyInvalidLicenseChanges,
emptyChanges,
emptyScorecard,
defaultConfig
)
const text = core.summary.stringify()
Expand All @@ -165,6 +196,7 @@ test('includes count and status icons for all findings', () => {
vulnerabilities,
licenseIssues,
emptyChanges,
emptyScorecard,
defaultConfig
)

Expand All @@ -184,6 +216,7 @@ test('uses checkmarks for license issues if only vulnerabilities were found', ()
vulnerabilities,
emptyInvalidLicenseChanges,
emptyChanges,
emptyScorecard,
defaultConfig
)

Expand All @@ -207,6 +240,7 @@ test('uses checkmarks for vulnerabilities if only license issues were found', ()
emptyChanges,
licenseIssues,
emptyChanges,
emptyScorecard,
defaultConfig
)

Expand Down
8 changes: 8 additions & 0 deletions action.yml
Expand Up @@ -65,6 +65,14 @@ inputs:
description: When set to `true` this action will always complete with success, overriding the `fail-on-severity` parameter.
required: false
default: false
show-openssf-scorecard:
description: Show a summary of the OpenSSF Scorecard scores.
required: false
default: true
warn-on-openssf-scorecard-level:
description: Numeric threshold for the OpenSSF Scorecard score. If the score is below this threshold, the action will warn you.
required: false
default: 3
outputs:
comment-content:
description: Prepared dependency report comment
Expand Down

0 comments on commit adaed32

Please sign in to comment.