Safeguard
Software Supply Chain•

How do you pin Buildkite plugins so a changed tag cannot hurt you?

Buildkite plugin tags can move. Pin plugin versions to a commit SHA, restrict plugin sources on the agent, and review every update before it ships.

Safeguard Security Team
4 min read

A Buildkite plugin reference such as docker#v5.13.0 resolves to a Git tag, and a tag can be moved. To keep a plugin from changing under you, pin it to the commit SHA of the tag, restrict which plugins agents may load, and update pins through reviewed pull requests.

How do Buildkite plugins get loaded?

Buildkite's documentation lists three sources. Plugins maintained by Buildkite live in the Buildkite Plugins GitHub organization and can be named by plugin name alone. Non-Buildkite plugins hosted on GitHub need the organization name too, as in my-org/docker#v5.13.0. Local, private and non-GitHub plugins use a full Git URL, followed by a version after the hash sign. Each form ends with a ref that tells the agent which version to check out and run on the build machine.

That last point is the risk. A plugin runs with the permissions of the agent: your source, your environment variables and often cloud credentials. Whoever controls what the ref points at controls what runs there.

What does pinning do?

The documentation says that to avoid a plugin's git tag contents being changed, you can use the commit SHA of the tag. Its example is the docker-compose plugin written with a short SHA after the hash sign. A commit SHA names exact content, while a tag is a label that a maintainer or an attacker with write access can move to different content. The documentation also shows referencing a branch for testing, which is fine on a dev pipeline and a poor choice in production because a branch moves with every push.

Constructed example: a team references a community plugin as my-org/cache#v2. A maintainer's account is taken over, and the v2 tag is moved to a commit that prints the agent's environment to a remote server. Pipelines using the tag pick it up on the next build. Pipelines using the SHA keep running the old, reviewed code.

What are the limits of pinning?

A pin freezes the plugin's own code, but a plugin may download tools or images when it runs, and those are separate trust decisions. You also take on an update task: pinned plugins do not receive fixes by themselves. Treat updating as a regular, reviewed change.

How do you limit which plugins can run?

The documentation points to its page on securing your Buildkite agent for selectively allowing and disallowing plugins, and notes that you can disable plugins entirely with the no-plugins option. For agents that only run trusted internal builds, an allow list of known repositories is much safer than letting any pipeline load any plugin.

What to do

  1. Inventory every plugin used across pipelines, including ones inherited from shared templates.
  2. Replace tag references with commit SHAs, keeping a comment with the human-readable version next to each.
  3. Remove branch references from production pipelines.
  4. Configure agents to allow only the plugin sources you trust, or disable plugins where you do not need them.
  5. Update pins through pull requests that show the diff between old and new plugin commits.
  6. Keep agent credentials short-lived and scoped, so a bad plugin has less to take.
  7. Re-run the inventory on a schedule and when pipeline files change.

Safeguard can inventory what your builds pull and apply policy gates on pull requests. Check the pipeline inventory with /demos/ci-cd-actions for an idea of how that looks.

Quick check

Is a version tag like v5.13.0 immutable?

No. Buildkite's documentation says to use the commit SHA to avoid a tag's contents being changed.

Does pinning replace reviewing plugins?

No. It stops silent changes, but you must still review the code you pin and each update.

Sources

Last reviewed: 18 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.