CyberSecurity

Harden Your Codebase

T

Temi Kara

September 02, 2026
8 min read
Views...
Harden Your Codebase

Your source code repository is the beating heart of your software supply chain. It holds not just your application logic, but the history of every decision, credential slip-up, and dependency choice your team has ever made. Yet many teams treat repository security as an afterthought something to bolt on after a breach rather than build in from day one. This post walks through four practical, high-leverage controls you can put in place today: metrics-driven security with the OpenSSF Scorecard, branch protection, automated code ownership, and a clear security policy.

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:

  1. 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.sarif

  2. Update your readme file with the script below so as to see your openSSF scores. [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/<your account>/<repo>/badge)](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.

branch rules

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.

security policy

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.

Related Articles