Safeguard
Security Guides•

How do you protect your build pipeline with three settings?

Three settings that protect a small team build pipeline: read only workflow tokens, actions pinned to commits and a protected main branch, with steps.

Safeguard Security Team
4 min read

Three settings do most of the work: make workflow tokens read only by default, pin third party actions to full commit hashes, and protect the main branch with required review and checks. Each takes under an hour and closes a common path from a stolen account or tampered action to your release.

Why the pipeline matters

Your build runs with credentials and produces what customers install. Whoever can change it can change your product. For a small team, it is also the cheapest place to add control, because the settings are free and central.

Setting one: read only tokens

GitHub's guidance for Actions says the token should have the minimum permissions required, and that it is good practice to set the default permission to read access for repository contents, then raise it per job as needed. Steps:

  1. Open the repository or organization Actions settings.
  2. Set default workflow permissions to read.
  3. Run your workflows and add write permission only to the jobs that fail without it.

Setting two: pin third party actions

A tag can be moved. A full length commit hash cannot be changed without creating a different object. The documentation says pinning to a commit helps mitigate the risk of a bad actor adding a backdoor to the action's repository, and advises checking that the hash is from the action's own repository and not a fork. Steps:

  1. List every third party action in your workflow files.
  2. Replace each tag with the full hash of the release you reviewed, keeping the tag in a comment.
  3. Let your update tool propose new hashes through pull requests.

The details are in how to pin GitHub Actions to SHAs correctly. The same documentation notes that pinning only to a tag is acceptable if you trust the creator, but a hash is stronger.

Setting three: protect main

GitHub's branch protection can require pull request reviews and passing status checks, and by default disables force pushes and deletion for the protected branch. It also states the restrictions do not apply to people with admin permissions unless you change the setting, so enable the option that includes administrators. See branch protection rules worth enabling.

Summary

SettingStopsTime
Read only tokensA compromised step from writing to your repositoryUnder an hour
Pinned actionsA changed action running in your buildAn hour or two
Protected mainUnreviewed changes reaching your release branchUnder an hour

Check your work

Open a test pull request that edits a workflow and watch what is required. Try a force push on a scratch branch. Confirm that secrets are not available to workflows triggered by untrusted changes. Verify at least one thing the hard way rather than trusting the settings page.

What these do not do

They do not scan your dependencies, and they do not protect the registry side. Pair them with locked installs and two factor on accounts. For a wider view, the OpenSSF Scorecard checks several of these practices on a project, and you can run it on your own repository.

Safeguard policies and gates on pull requests add dependency checks to the same flow. A free scan is at https://gold.safeguard.sh/scan.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

Do these settings cost anything?

They are settings in GitHub, but plan availability differs for some features, so check the documentation for your plan.

Will pinning break my workflows?

It should not, because you pin to the release you already use. You then update through reviewed pull requests.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.