Skip to content

Commit

Permalink
Initial implementation, tests, readme
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed May 24, 2023
1 parent 2df2fab commit c3985f2
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"root": true,

"extends": "@ljharb/eslint-config/node/18",
}
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# These are supported funding model platforms

github: [ljharb]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/scorecard-cli
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
7 changes: 7 additions & 0 deletions .github/workflows/node-pretest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: 'Tests: pretest/posttest'

on: [pull_request, push]

jobs:
tests:
uses: ljharb/actions/.github/workflows/pretest.yml@main
18 changes: 18 additions & 0 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: 'Tests: node.js'

on: [pull_request, push]

jobs:
tests:
uses: ljharb/actions/.github/workflows/node.yml@main
with:
range: '^18.16.0 || ^20.2.0'
type: minors
command: npm run tests-only

node:
name: 'node (engines.node)'
needs: [tests]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'
22 changes: 22 additions & 0 deletions .github/workflows/rebase.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Automatic Rebase

on: [pull_request_target]

permissions:
contents: read

jobs:
_:
permissions:
contents: write # for ljharb/rebase to push code to rebase
pull-requests: read # for ljharb/rebase to get info about PR

name: "Automatic Rebase"

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: ljharb/rebase@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
12 changes: 12 additions & 0 deletions .github/workflows/require-allow-edits.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Require “Allow Edits”

on: [pull_request_target]

jobs:
_:
name: "Require “Allow Edits”"

runs-on: ubuntu-latest

steps:
- uses: ljharb/require-allow-edits@main
13 changes: 13 additions & 0 deletions .nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"all": true,
"check-coverage": false,
"reporter": ["text-summary", "text", "html", "json"],
"lines": 86,
"statements": 85.93,
"functions": 82.43,
"branches": 76.06,
"exclude": [
"coverage",
"test"
]
}
226 changes: 225 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,226 @@
# scorecard-cli
# scorecard-cli <sup>[![Version Badge][npm-version-svg]][package-url]</sup>

[![github actions][actions-image]][actions-url]
[![coverage][codecov-image]][codecov-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]

[![npm badge][npm-badge-png]][package-url]

A CLI for OpenSSF Scorecard data.

## Example

### CLI

```console
> scorecard-cli ljharb/qs
{
date: '2023-05-22',
repo: {
name: 'github.com/ljharb/qs',
commit: '410bdd3c8ae7f5d7ae9b52648b8642b8adc5e1c0'
},
scorecard: {
version: 'v4.10.5-188-g028fa93',
commit: '028fa93e924d3facde890a113f7edf1225a87ea2'
},
score: 6.8,
checks: [
{
name: 'Maintained',
score: 8,
reason: '4 commit(s) out of 30 and 6 issue activity out of 30 found in the last 90 days -- score normalized to 8',
details: null,
documentation: {
short: 'Determines if the project is "actively maintained".',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#maintained'
}
},
{
name: 'Code-Review',
score: 0,
reason: 'found 26 unreviewed human changesets (30 total)',
details: null,
documentation: {
short: 'Determines if the project requires human code review before pull requests (aka merge requests) are merged.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#code-review'
}
},
{
name: 'CII-Best-Practices',
score: 0,
reason: 'no effort to earn an OpenSSF best practices badge detected',
details: null,
documentation: {
short: 'Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#cii-best-practices'
}
},
{
name: 'License',
score: 10,
reason: 'license file detected',
details: [
'Info: License file found in expected location: LICENSE.md:1',
'Info: FSF or OSI recognized license: LICENSE.md:1'
],
documentation: {
short: 'Determines if the project has defined a license.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#license'
}
},
{
name: 'Branch-Protection',
score: -1,
reason: 'internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration',
details: null,
documentation: {
short: "Determines if the default and release branches are protected with GitHub's branch protection settings.",
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#branch-protection'
}
},
{
name: 'Signed-Releases',
score: -1,
reason: 'no releases found',
details: [ 'Warn: no GitHub releases found' ],
documentation: {
short: 'Determines if the project cryptographically signs release artifacts.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#signed-releases'
}
},
{
name: 'Binary-Artifacts',
score: 10,
reason: 'no binaries found in the repo',
details: null,
documentation: {
short: 'Determines if the project has generated executable (binary) artifacts in the source repository.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#binary-artifacts'
}
},
{
name: 'Pinned-Dependencies',
score: 8,
reason: 'dependency not pinned by hash detected -- score normalized to 8',
details: [
'Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rebase.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/ljharb/qs/rebase.yml/main?enable=pin',
'Warn: third-party GitHubAction not pinned by hash: .github/workflows/rebase.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/ljharb/qs/rebase.yml/main?enable=pin',
'Warn: third-party GitHubAction not pinned by hash: .github/workflows/require-allow-edits.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/ljharb/qs/require-allow-edits.yml/main?enable=pin',
'Info: Dockerfile dependencies are pinned',
'Info: no insecure (not pinned by hash) dependency downloads found in Dockerfiles',
'Info: no insecure (not pinned by hash) dependency downloads found in shell scripts',
'Info: Pip installs are pinned'
],
documentation: {
short: 'Determines if the project has declared and pinned the dependencies of its build process.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#pinned-dependencies'
}
},
{
name: 'Dangerous-Workflow',
score: 10,
reason: 'no dangerous workflow patterns detected',
details: null,
documentation: {
short: "Determines if the project's GitHub Action workflows avoid dangerous patterns.",
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#dangerous-workflow'
}
},
{
name: 'Packaging',
score: -1,
reason: 'no published package detected',
details: [ 'Warn: no GitHub/GitLab publishing workflow detected' ],
documentation: {
short: 'Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#packaging'
}
},
{
name: 'Token-Permissions',
score: 10,
reason: 'tokens are read-only in GitHub workflows',
details: [
"Info: topLevel 'contents' permission set to 'read': .github/workflows/node-aught.yml:6",
"Info: topLevel 'contents' permission set to 'read': .github/workflows/node-pretest.yml:6",
"Info: topLevel 'contents' permission set to 'read': .github/workflows/node-tens.yml:6",
"Info: topLevel 'contents' permission set to 'read': .github/workflows/rebase.yml:6",
"Warn: jobLevel 'contents' permission set to 'write': .github/workflows/rebase.yml:11: Verify which permissions are needed and consider whether you can reduce them. (High effort)",
"Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/rebase.yml:12",
"Info: topLevel 'contents' permission set to 'read': .github/workflows/require-allow-edits.yml:6",
"Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/require-allow-edits.yml:11"
],
documentation: {
short: "Determines if the project's workflows follow the principle of least privilege.",
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#token-permissions'
}
},
{
name: 'Vulnerabilities',
score: 10,
reason: 'no vulnerabilities detected',
details: null,
documentation: {
short: 'Determines if the project has open, known unfixed vulnerabilities.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#vulnerabilities'
}
},
{
name: 'Fuzzing',
score: 0,
reason: 'project is not fuzzed',
details: null,
documentation: {
short: 'Determines if the project uses fuzzing.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#fuzzing'
}
},
{
name: 'Security-Policy',
score: 9,
reason: 'security policy file detected',
details: [
'Info: Found linked content in security policy: github.com/ljharb/.github/SECURITY.md',
'Info: Found text in security policy: github.com/ljharb/.github/SECURITY.md',
'Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy: github.com/ljharb/.github/SECURITY.md',
'Info: security policy detected in org repo: github.com/ljharb/.github/SECURITY.md'
],
documentation: {
short: 'Determines if the project has published a security policy.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#security-policy'
}
},
{
name: 'SAST',
score: 0,
reason: 'SAST tool is not run on all commits -- score normalized to 0',
details: [
'Warn: 0 commits out of 5 are checked with a SAST tool',
'Warn: CodeQL tool not detected'
],
documentation: {
short: 'Determines if the project uses static code analysis.',
url: 'https://github.com/ossf/scorecard/blob/028fa93e924d3facde890a113f7edf1225a87ea2/docs/checks.md#sast'
}
}
]
}
```

[package-url]: https://npmjs.org/package/scorecard-cli
[npm-version-svg]: https://versionbadg.es/ljharb/scorecard-cli.svg
[deps-svg]: https://david-dm.org/ljharb/scorecard-cli.svg
[deps-url]: https://david-dm.org/ljharb/scorecard-cli
[dev-deps-svg]: https://david-dm.org/ljharb/scorecard-cli/dev-status.svg
[dev-deps-url]: https://david-dm.org/ljharb/scorecard-cli#info=devDependencies
[npm-badge-png]: https://nodei.co/npm/scorecard-cli.png?downloads=true&stars=true
[license-image]: https://img.shields.io/npm/l/scorecard-cli.svg
[license-url]: LICENSE
[downloads-image]: https://img.shields.io/npm/dm/scorecard-cli.svg
[downloads-url]: https://npm-stat.com/charts.html?package=scorecard-cli
[codecov-image]: https://codecov.io/gh/ljharb/scorecard-cli/branch/main/graphs/badge.svg
[codecov-url]: https://app.codecov.io/gh/ljharb/scorecard-cli/
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/scorecard-cli
[actions-url]: https://github.com/ljharb/scorecard-cli/actions
24 changes: 24 additions & 0 deletions bin/scorecard-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env node

'use strict';

const { inspect, parseArgs } = require('util');

const { positionals } = parseArgs({ allowPositionals: true });

if (positionals.length !== 1) {
console.error('Expected exactly one positional argument: the repository slug (e.g. "nvm-sh/nvm")');
process.exit(1);
}

// module.exports assignment is solely for testing.
module.exports = import('@nodesecure/ossf-scorecard-sdk').then(async ({ result }) => {
const results = await result(positionals[0]);

const output = inspect(results, { colors: process.env.TERM !== 'dumb', depth: Infinity });

console.log(output);
}).catch((e) => {
console.error(e);
process.exit(1);
});

0 comments on commit c3985f2

Please sign in to comment.