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 support for calculating OpenSSF Scorecards #709

Merged
merged 53 commits into from Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3d70a3c
Draft integration with deps.dev
jhutchings1 Mar 2, 2024
f419e37
Fix build breaks
jhutchings1 Mar 3, 2024
7a8ce50
Update dist
jhutchings1 Mar 3, 2024
781bff1
Fix prettier issues, and JSON error in main
jhutchings1 Mar 3, 2024
af5438b
Add debugging
jhutchings1 Mar 3, 2024
4230610
Add exception handling
jhutchings1 Mar 3, 2024
d641d3a
Fix bugs in scorecard
jhutchings1 Mar 3, 2024
f87cc24
Fixing bugs
jhutchings1 Mar 3, 2024
e16e218
Encode URI component to fix 404
jhutchings1 Mar 3, 2024
f357c75
fix extra slash
jhutchings1 Mar 3, 2024
b2ddac1
Remove custom type to go around errors
jhutchings1 Mar 3, 2024
72d5b06
Add more error handling
jhutchings1 Mar 3, 2024
ffd129c
Refactor types, add printing
jhutchings1 Mar 3, 2024
f1b66d1
Remove dependency on PackageURL
jhutchings1 Mar 3, 2024
bf2683a
Fixing url error
jhutchings1 Mar 3, 2024
764e39e
Attempt to fix type issues
jhutchings1 Mar 3, 2024
43286af
Add debugging
jhutchings1 Mar 3, 2024
6bcbf04
Fix OpenSSF Scorecard Score retrieval
jhutchings1 Mar 3, 2024
c286ea9
Add nullish to types
jhutchings1 Mar 3, 2024
2bc3ecb
Fix type issues
jhutchings1 Mar 3, 2024
7d2e20d
Stub out summary implementation for scorecards
jhutchings1 Mar 4, 2024
5955069
Add debugging
jhutchings1 Mar 4, 2024
ea64ae9
Fix config mapping issue
jhutchings1 Mar 4, 2024
2fcc6a1
Fix config implementation
jhutchings1 Mar 4, 2024
9843156
Improve summary formatting
jhutchings1 Mar 4, 2024
94125c4
Fix formatting issues
jhutchings1 Mar 4, 2024
1251834
Add dependencies without scorecards to scorecards table
jhutchings1 Mar 4, 2024
f8ebb4b
Add formatting around warning for low scorecard levels
jhutchings1 Mar 4, 2024
5bace73
Fix undefined/null checks
jhutchings1 Mar 4, 2024
b3d2872
Update dist
jhutchings1 Mar 4, 2024
b5a1aee
Add debugging
jhutchings1 Mar 4, 2024
29b9ef4
Fix icons and undefined/null checks
jhutchings1 Mar 4, 2024
a1258f2
Fix icon issues
jhutchings1 Mar 4, 2024
111227a
Refactor scorecard API implementation
jhutchings1 Mar 6, 2024
1b21f39
Fix scorecard bug
jhutchings1 Mar 6, 2024
e878bf8
Fix bug with protocol prefixes
jhutchings1 Mar 6, 2024
59d4782
Add links to summary
jhutchings1 Mar 6, 2024
296bf3a
Add docs, implement warning behavior
jhutchings1 Mar 8, 2024
cb0a041
Update dist
jhutchings1 Mar 8, 2024
250250e
Refactor schema, add line numbers to warnings
jhutchings1 Mar 8, 2024
6a74ebd
Fix column number implementation
jhutchings1 Mar 8, 2024
5ba0d0f
Add debugging
jhutchings1 Mar 8, 2024
5bc1976
Add debugging
jhutchings1 Mar 8, 2024
70801db
Revert line number implementation
jhutchings1 Mar 11, 2024
ba6b805
Remove dead code, complete printScorecardBlock
jhutchings1 Mar 11, 2024
b7fdb4c
Remove unused import
jhutchings1 Mar 11, 2024
d186d66
Automatically collapse the scorecard table
jhutchings1 Mar 11, 2024
ac60038
Add tests
jhutchings1 Mar 12, 2024
7dc5f53
Add scorecard to summary and count scorecard warnings
jhutchings1 Mar 12, 2024
7266669
Fix broken tests, clean up dead code
jhutchings1 Mar 12, 2024
f875e6e
Simplify truthiness check
jhutchings1 Mar 12, 2024
0e8bc32
Fix prettier linting
jhutchings1 Mar 12, 2024
4ce1201
Fix OpenSSF Scorecard display issue
jhutchings1 Mar 13, 2024
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
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