Skip to content
Français
Sécurité medium

OpenSSF Scorecard

2 min de lecture

Read this page in French

OpenSSF Scorecard logo

In March 2024, XZ Utils, a compression utility present on nearly every Linux server, was compromised by a backdoor hidden over two years. The attacker had earned the maintainer's trust, obtained commit rights, then injected malicious code allowing remote code execution through SSH. That attack captures the software supply chain dilemma perfectly: how do you trust dependencies maintained by strangers?

Supply chain attacks are exploding. According to Sonatype, they rose by 245% in three years. SolarWinds, Event-Stream, Polyfill.io, tj-actions: every incident shows that the popularity of a project does not guarantee its security. An npm package with millions of downloads can be taken over by an attacker. A GitHub action with thousands of stars can exfiltrate your secrets.

The fundamental problem: we trust blindly. We install hundreds of dependencies without checking who maintains them, how they are built, whether the releases are signed. We use GitHub actions with mutable tags (@v1) that can change at any moment. We load scripts from third-party CDNs with no control.

OpenSSF Scorecard gives an objective answer to that question of trust. This tool, built by the Open Source Security Foundation, analyses a GitHub repository automatically and gives it a score from 0 to 10 based on concrete security criteria: branch protection, code reviews, signatures, known vulnerabilities, dangerous patterns in the workflows, and more.

What you will learn

  • Understand what Scorecard evaluates and how to read the results
  • Install and use the CLI against a public repository
  • Wire Scorecard into a CI/CD pipeline, on GitHub and on GitLab
  • Read the 19 checks and know the remediation for each score
  • Raise your score through a progressive action plan

What is OpenSSF Scorecard?

Scorecard is an automated tool measuring the security posture of an open source project. It runs a series of checks (heuristic controls) and produces a score for each of them.

The idea is simple: rather than trusting a dependency blindly, you objectively verify whether the project follows security good practices.

Why it is useful

  1. Assessing a dependency before adoption: a score below 5 should raise a flag
  2. Auditing your own projects: identifying the weaknesses to fix
  3. Proving your security maturity: showing a score badge in your README
  4. Automating the monitoring: wiring Scorecard into the CI/CD

What Scorecard evaluates

Scorecard analyses varied aspects of a project's security:

CategoryExample checks
Code protectionBranch Protection, Code Review, Signed Releases
Build qualityPinned Dependencies, CI Tests, Fuzzing
MaintenanceActive maintainers, response to vulnerabilities
Operational securityDangerous Workflows, Token Permissions

Every check returns a score from 0 to 10 with a reason explaining the result.

Installation

Scorecard can be installed in several ways depending on the environment.

Fenêtre de terminal
# Get the latest available version
VERSION=$(curl -s https://api.github.com/repos/ossf/scorecard/releases/latest | grep tag_name | cut -d '"' -f 4)
# Download the release
wget "https://github.com/ossf/scorecard/releases/download/${VERSION}/scorecard_${VERSION#v}_linux_amd64.tar.gz"
# Extract and install
tar xzf scorecard_*_linux_amd64.tar.gz
sudo install scorecard /usr/local/bin/scorecard
# Check the installation
scorecard version

Basic usage

Configuring GitHub authentication

A GitHub token is required

Without a GitHub token, Scorecard hits the API limits very quickly (60 requests per hour). In practice, a token is indispensable to analyse a project.

Token type and permissions:

Token typeRequired scopeLimitation
Classic tokenpublic_repo (or repo for private repositories)Full access to every check
Fine-grained tokenContents: read, Metadata: readCannot read the classic branch protection rules

Recommendation

To obtain the Branch-Protection score, use a classic token with the public_repo scope. Fine-grained tokens produce an error on that check because they have no access to GitHub's classic protection rules. See the official documentation.

Fenêtre de terminal
# Create a classic token at https://github.com/settings/tokens
# Minimal scope: public_repo (or repo for private repositories)
# Export the token
export GITHUB_AUTH_TOKEN=ghp_xxxxxxxxxxxx

Analysing a GitHub project

Once the token is configured, the basic command analyses a repository:

Fenêtre de terminal
# Analyse a public project
scorecard --repo=github.com/kubernetes/kubernetes

Reading the output

Scorecard prints a summary per check. Here is a real example on the Kubernetes project:

Aggregate score: 6.8 / 10
Check scores:
|---------|------------------------|-----------------------------------------------------------------------|
| SCORE | NAME | REASON |
|---------|------------------------|-----------------------------------------------------------------------|
| 10 / 10 | Binary-Artifacts | no binaries found in the repo |
| 10 / 10 | CI-Tests | 13 out of 13 merged PRs checked by a CI test |
| 5 / 10 | CII-Best-Practices | badge detected: Passing |
| 8 / 10 | Code-Review | Found 13/16 approved changesets |
| 10 / 10 | Contributors | project has 37 contributing companies or organizations |
| 0 / 10 | Dependency-Update-Tool | no update tool detected |
| 10 / 10 | Fuzzing | project is fuzzed |
| 10 / 10 | License | license file detected |
| 10 / 10 | Maintained | 30 commit(s) and 4 issue activity found in the last 90 days |
| 0 / 10 | Pinned-Dependencies | dependency not pinned by hash detected |
| 0 / 10 | SAST | SAST tool is not run on all commits |
| 10 / 10 | Security-Policy | security policy file detected |
| 8 / 10 | Vulnerabilities | 2 existing vulnerabilities detected |
|---------|------------------------|-----------------------------------------------------------------------|

Checks showing "?"

Some checks can show ? instead of a score. That means the check could not run (insufficient data, token permissions, or a feature the project does not use).

Output formats

Scorecard supports several formats for integration with other tools:

Fenêtre de terminal
# JSON format for automated processing
scorecard --repo=github.com/org/project --format=json > scorecard.json
# SARIF format for GitHub Security
scorecard --repo=github.com/org/project --format=sarif > scorecard.sarif

The checks in detail

Scorecard runs 19 checks spread across several categories. Each check evaluates one specific security aspect and gives a score from 0 to 10. Here is the full list with the evaluation criteria and the actions that raise each score.

Critical checks (high risk)

Binary-Artifacts

Risk: unauditable code in the repository.

Checks the absence of executable binary files (.exe, .class, .pyc, minified JS, and so on) in the source code. Binaries cannot be reviewed and may carry malicious or obsolete code.

Score 10/10: no binary found in the repository.

Remediation: remove the binaries and generate them from the source code at build time.

Branch-Protection

Risk: malicious code injected with no control.

Checks that the main branches (main, master) are protected through the GitHub protection rules.

The tiered scale:

PointsRequirements
3/10Force push and branch deletion forbidden
6/10+ At least 1 reviewer required, pull request mandatory before merge
8/10+ At least 1 required CI status check
9/10+ At least 2 reviewers, review by code owners
10/10+ Approvals dismissed after a new commit, admins included

Remediation: configure the protection rules under Settings > Branches > Branch protection rules on GitHub.

Code-Review

Risk: vulnerabilities or malicious code going undetected.

Measures whether changes pass through human review before integration. It analyses the last 30 commits to check they were approved.

The scale:

  • -7 points if a human change is not reviewed
  • -3 additional points if several changes are not reviewed
  • -3 points if bot changes are not reviewed

AI reviews

Reviews by bots (including AI/ML ones) do not count as code review, because they do not guarantee that a second person understood the change.

Remediation: make reviews mandatory through the branch protection rules.

Dangerous-Workflow

Risk: repository compromise (critical).

Detects dangerous patterns in GitHub Actions workflows:

  • Untrusted checkout: pull_request_target or workflow_run with an explicit checkout of the pull request, which lets the pull request author run arbitrary code with the repository secrets
  • Script injection: unsanitised GitHub context variables in inline scripts (for example ${{ github.event.issue.title }})

Score 10/10: no dangerous pattern detected.

Remediation: read the GitHub Security Lab guide and the Securing pull_request_target guide.

Signed-Releases

Risk: installing malicious releases.

Checks that releases are signed cryptographically. It analyses the last 5 releases for the presence of signature files.

Extensions looked for: .minisig, .asc (PGP), .sig, .sign, .sigstore, .sigstore.json, .intoto.jsonl (SLSA).

The scale:

  • 8/10: a signature present for every release
  • 10/10: a SLSA attestation (.intoto.jsonl) present

Remediation: sign your releases and publish provenance attestations; see GitHub Actions attestations.

Token-Permissions

Risk: tokens holding excessive permissions.

Checks that GitHub Actions workflows follow the principle of least privilege for the GITHUB_TOKEN.

The optimal score: permissions set to read-only at the global level, and write permissions declared only on the jobs that need them.

# ✅ Good practice
permissions:
contents: read # Read-only by default
jobs:
deploy:
permissions:
contents: write # Write for this job only

Remediation: use StepSecurity to work out the minimal permissions needed, and see GITHUB_TOKEN permissions.

Vulnerabilities

Risk: known, exploitable vulnerabilities.

Checks through OSV (Open Source Vulnerabilities) whether the project or its dependencies carry open, unfixed vulnerabilities.

The score: depends on the number and the severity of the vulnerabilities detected.

Remediation: fix the vulnerabilities in the code or update the dependencies to non-vulnerable versions.

Build quality checks

CI-Tests

Risk: bugs and vulnerabilities going undetected.

Checks whether the project runs automated tests before merging pull requests. It analyses the last 30 commits for the presence of CI checks.

Systems detected: GitHub Actions, Travis CI, CircleCI, Jenkins, AppVeyor, BuildKite, Woodpecker, and any system whose name contains "test" or "e2e".

Score 10/10: every recent commit went through CI tests.

Remediation: add tests with GitHub Actions or another CI system.

Dependency-Update-Tool

Risk: outdated dependencies carrying known vulnerabilities.

Checks whether the project uses an automatic dependency update tool.

Tools detected:

Score 10/10: a configuration file for one of those tools is detected.

Remediation: enable Dependabot in the GitHub settings or configure Renovate at the root of the project.

Fuzzing

Risk: undiscovered vulnerabilities in the code.

Checks whether the project uses fuzzing (testing with random data) to find bugs.

Methods detected:

  • Inclusion in OSS-Fuzz
  • ClusterFuzzLite in the repository
  • Native Go fuzz tests (func FuzzXxx)
  • Property-based testing libraries (QuickCheck, fast-check, FsCheck, and so on)

Remediation: add the project to OSS-Fuzz or use the language's native fuzzing.

Pinned-Dependencies

Risk: compromised dependencies (a supply chain attack).

Checks that dependencies are pinned to hashes rather than to mutable versions or tags.

What is analysed:

  • GitHub actions (they must use a SHA, not @v1)
  • Docker images (they must use a digest)
  • Dependencies in shell scripts and Dockerfiles
# ❌ A mutable tag: it can change without notice
- uses: actions/checkout@v4
# ✅ A pinned SHA: immutable
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

Remediation: use StepSecurity to pin the actions automatically, and Renovate with pinDigests: true for the Docker images. The procedure is detailed in Pinning actions by SHA.

SAST

Risk: bugs and vulnerabilities in the source code.

Checks whether the project runs static application security testing (SAST) on pull requests.

Tools detected:

  • CodeQL (github-code-scanning)
  • SonarCloud
  • The github/codeql-action action in the workflows

Remediation: enable CodeQL under Settings > Security > Code scanning or add the github/codeql-action action to a workflow.

Governance checks

CII-Best-Practices

Risk: security good practices not followed.

Checks whether the project earned an OpenSSF Best Practices badge.

The scale:

  • 2/10: badge in progress
  • 5/10: "Passing" badge
  • 7/10: "Silver" badge
  • 10/10: "Gold" badge

Remediation: register on bestpractices.dev and fill in the questionnaire.

Contributors

Risk: a project depending on a single organisation.

Checks whether the project has contributors from several different organisations (based on the "Company" field of the GitHub profiles).

Score 10/10: at least 3 different organisations among the last 30 commits, with at least 5 commits each.

Remediation: encourage contributors to fill in their organisation in their GitHub profile.

License

Risk: an obstacle to security auditing, and a legal risk.

Checks for the presence of a licence in the repository.

The scale:

  • 6/10: a LICENSE, COPYING or COPYRIGHT file detected
  • 9/10: + the file at the root of the project
  • 10/10: + a licence recognised by the FSF or OSI (an SPDX identifier)

Remediation: add a LICENSE file at the root with an SPDX licence.

Maintained

Risk: unfixed vulnerabilities in an abandoned project.

Evaluates the recent activity of the project over the last 90 days.

Score 10/10: at least 1 commit per week over the last 90 days.

Partial score: issue activity from collaborators or maintainers.

Score 0: an archived project.

Careful

An inactive project can be the target of a maintainer takeover, an attacker regaining control to inject malicious code (see XZ Utils).

Security-Policy

Risk: insecure reporting of vulnerabilities.

Checks for the presence of a SECURITY.md file explaining how to report vulnerabilities responsibly.

The scale:

  • 6/10: a contact email or URL present
  • 9/10: + explanatory text beyond the bare links
  • 10/10: + disclosure timelines mentioned (for example "90 days")

Remediation: create a SECURITY.md file at the root with the reporting instructions. On GitHub, use Settings > Security > Security advisories.

Other checks

Packaging

Checks whether the project publishes packages through GitHub Packages or publication actions towards npm, PyPI and others.

SBOM

Checks for the presence of an SBOM in the source code or in the release artefacts.

Webhooks

Checks that the configured webhooks use a secret to authenticate the requests.

CI/CD integration

GitHub Actions

The native integration runs Scorecard automatically and publishes the results in the GitHub Security tab:

.github/workflows/scorecard.yml
name: Scorecard Analysis
on:
push:
branches: [ "main" ]
schedule:
# Weekly analysis on Sunday at midnight
- cron: '0 0 * * 0'
permissions:
# Needed to publish the results
security-events: write
id-token: write
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run analysis
uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4c4f1698e080
with:
sarif_file: results.sarif

Publishing the results

The publish_results: true option shows the score on securityscorecards.dev and gives you a badge for the README.

GitLab CI

On GitLab, you use the CLI directly:

.gitlab-ci.yml
scorecard:
stage: security
image: gcr.io/openssf/scorecard:v5.5.0@sha256:b9a535801cb5fc8e7b2bea4cf45dd2db9a342cab8cc32bb5be2ac1355a95356f
variables:
GITHUB_AUTH_TOKEN: $GITLAB_TOKEN
script:
- scorecard --repo=gitlab.com/$CI_PROJECT_PATH --format=json > scorecard.json
artifacts:
reports:
codequality: scorecard.json
paths:
- scorecard.json
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Showing the score badge

Once the results are published, you can add a badge to the README to show the hardening effort:

![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/my-org/my-project/badge)

The badge updates automatically after each analysis.

Raising your score

Here is a progressive action plan to raise a project's score:

  1. Enable branch protection

    In the GitHub settings, configure:

    • Mandatory review by at least 1 person
    • Required CI statuses before merge
    • Force push forbidden
  2. Pin the dependencies

    Replace every mutable tag with a SHA in the GitHub Actions workflows and the Dockerfiles.

  3. Sign the releases

    Sign the artefacts and publish provenance attestations.

  4. Enable Dependabot or Renovate

    Configure automatic dependency updates to receive the security fixes.

  5. Audit the workflows

    Check there is no dangerous pattern and minimise the token permissions.

Scorecard in a DevSecOps strategy

Scorecard fits naturally into a wider supply chain security approach. It checks the development practices upstream, while the scanners detect the vulnerabilities in the artefacts produced. The combination gives you defence in depth: a repository can hold no known CVE and still be one stolen maintainer account away from compromise, which is exactly what Scorecard measures and a scanner does not.

Key points

  • Scorecard gives an objective answer to the question of trusting an open source project, in seconds.
  • Analyse your critical dependencies before adoption: a score below 5 should raise a flag.
  • Wire Scorecard into your CI/CD to watch your own projects over time, with a weekly schedule.
  • The three checks that move the needle fastest are Branch-Protection, Pinned-Dependencies and Token-Permissions.
  • Show the badge to make the security effort visible, and combine Scorecard with artefact scanners for defence in depth.
  • A good Scorecard score does not guarantee the absence of vulnerabilities, but it significantly cuts the risk of a maintainer takeover and of supply chain attacks like the XZ Utils one.

Next steps

Resources

Is this site useful to you?

Fewer than 1% of readers support this site.

I maintain more than 700 free guides, with no ads and no tracking. Any support, even a symbolic one, helps cover hosting and keeps these resources free. Thank you for the help.

The form does not show? Open Ko-fi in a new tab.

Subscribe and follow my DevSecOps work on LinkedIn