OpenSSF Scorecard
You can't improve what you don't measure. The OpenSSF Scorecard is an open-source tool that automatically evaluates a repository against a set of security best practices and produces a score from 0 to 10.
Scorecard checks things like:
Branch protection enabled
Code review required before merging
Dependencies pinned to specific versions
Project has a security policy
CI/CD workflows follow least-privilege token permissions
Known-vulnerable dependencies are present
Why it matters: Scorecard turns "security posture" from a vague feeling into a number you can track over time, compare across repositories, and use to justify investment. Many organizations run Scorecard as a GitHub Action on every push, publish the results as a badge in their README, and use the score as a gate in their internal compliance dashboards.
Getting started:
Create a workflow and add the script below to the workflow file, you can also get openSSF scorecard in market place.
# This workflow uses actions that are not certified by GitHub. They are provided # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. name: Scorecard supply-chain security on: # For Branch-Protection check. Only the default branch is supported. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection branch_protection_rule: # To guarantee Maintained check is occasionally updated. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained schedule: - cron: '24 0 * * 6' push: branches: [ "main" ] # Declare default permissions as read only. permissions: read-all jobs: analysis: name: Scorecard analysis runs-on: ubuntu-latest # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled. if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request' permissions: # Needed to upload the results to code-scanning dashboard. security-events: write # Needed to publish results and get a badge (see publish_results below). id-token: write # Uncomment the permissions below if installing in a private repository. # contents: read # actions: read steps: - name: "Checkout code" uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 with: results_file: results.sarif results_format: sarif # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: # - you want to enable the Branch-Protection check on a *public* repository, or # - you are installing Scorecard on a *private* repository # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. # repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers # - Allows the repository to include the Scorecard badge. # - See https://github.com/ossf/scorecard-action#publishing-results. # For private repositories: # - `publish_results` will always be set to `false`, regardless # of the value entered here. publish_results: true # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore # file_mode: git # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 with: name: SARIF file path: results.sarif retention-days: 5 # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarifUpdate your readme file with the script below so as to see your openSSF scores.
[](https://scorecard.dev/viewer/?uri=github.com/<your account>/<repo>)
N.B: ensure to replace <your account> and <repo> with your account name and repo name
Once it's running, treat a dropping score the same way you'd treat a failing test, investigate and fix it.
Branch Protection
Branch protection rules are your first line of defence against accidental or malicious changes landing directly in production critical branches. Without them, anyone with write access can push straight to main branch, force-push over history, or delete a branch outright.
At a minimum, your protected branches (usually main and any release branches) should require:
Pull requests before merging
At least one (ideally two) approving reviews
Status checks to pass
Signed commits
No force pushes and no branch deletion
Up-to-date branches
Why it matters: Branch protection converts "trust everyone with access" into "trust the process." Even a well meaning senior engineer can fat-finger a push, a compromised laptop or leaked token becomes far less dangerous when it can't unilaterally rewrite main branch.
Most Git hosting platforms (GitHub, GitLab, Bitbucket) support this natively through rulesets or protected branch settings, there's no excuse not to turn it on.

Code Ownership: Automating Reviewer Assignment
Requiring a review is only half the battle, the right people need to review the right changes. That's where code ownership comes in.
Tools like GitHub's CODEOWNERS file let you map paths in your repository to specific people or teams, so that whenever a pull request touches those paths, the right reviewers are automatically requested.
Create a CODEOWNERS file in .github file and map out ownership based on teams or individuals.
# .github/CODEOWNERS
# Default owners for everything
* @platform-team
# Infrastructure and CI/CD
/infra/ @devops-team
/.github/workflows/ @devops-team @security-team
# Authentication and authorization logic
/src/auth/ @security-team
# Frontend
/src/ui/ @frontend-team
Why it matters: This removes the "I assumed someone else would review it" gap. Sensitive areas of the codebase like authentication, payment processing, CI/CD pipelines, get eyes from people who actually understand the risk, every single time, without relying on the PR author to remember to tag them.
Pair CODEOWNERS with branch protection's "require review from code owners" setting, and you've closed a very common gap: critical code changing hands without the right scrutiny.
Security Policy
A SECURITY.md file might seem like a formality, but it's one of the highest-leverage documents you can add to a repository. It answers a question that security researchers, well-meaning users, and even automated scanners frequently ask: "If I find a vulnerability, what do I do?"
A good security policy includes:
Supported versions
which releases receive security patches
How to report a vulnerability
a dedicated email address or private reporting mechanism (GitHub's private vulnerability reporting is a good option)
Expected response time
sets expectations and builds trust
Disclosure policy
coordinated disclosure timelines, whether you run a bug bounty, and how credit is given
# Security Policy
### Reporting Security Issues
We take security bugs in our repository seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/<your account>/<repo>/security/advisories/new) tab.

Why it matters: Without a clear policy, vulnerabilities often get reported publicly (via an open issue), get ignored because there's no clear owner, or simply never get reported at all because the researcher couldn't find a contact path. A SECURITY.md closes that gap and is, not coincidentally, one of the checks OpenSSF Scorecard looks for directly.
Conclusion
These four controls compound:
Scorecard
gives you visibility and an ongoing metric to track.
Branch protection
enforces process at the repository level.
Code ownership
ensures the right humans are in the loop.
A security policy
gives outsiders a safe, clear path to help you.
None of these require a large security team or a big budget, most take under an hour to configure. Start with branch protection and a CODEOWNERS file today, add a SECURITY.md this week, and wire up Scorecard to track your progress going forward. Small, consistent controls like these are what separate repositories that get quietly exploited from ones that don't.


