Safeguard
Application Security•

How do you stop a pull request from hijacking your Jenkins build?

A pull request can change the code Jenkins runs. Keep untrusted changes away from credentials and the controller, and review which builds run fork code.

Safeguard Security Team
4 min read

A pull request can change the Jenkinsfile, the build scripts and the tests, so building it means running the author's code. To protect Jenkins, keep builds off the controller, keep trusted credentials out of pull request builds, and only auto build changes from people you already trust.

Why is a pull request a risk in the first place?

CI builds a proposed change before a human has merged it. That is the point of CI. But the change can include anything that executes: a modified Jenkinsfile, a test that opens a network socket, a build script that reads environment variables.

Security researchers call this a poisoned pipeline execution. The attacker never needs to break into Jenkins. They send a pull request and let your own job run their code, with whatever access the job has.

Consider a constructed example. A public repository uses a multibranch job. A contributor opens a pull request that edits a test helper to print every environment variable to a file the job archives. If the job was configured with a deploy token available to all branches, that token is now in a downloadable artifact.

What does Jenkins itself say about this?

The Securing Jenkins chapter makes a few points that apply directly:

  • Builds should not run on the built-in node, which is the controller. The page calls this just the beginning, and says more steps are needed to keep builds from affecting the controller.
  • Builds can interfere with each other and with your infrastructure, so restrict what a running build can do.
  • Environment variables, including those injected as build parameters, can make scripts behave differently than intended. Write build scripts defensively.
  • Organization folder and multibranch pipeline credentials may be accessible to unprivileged users in ways you might not expect.

The Jenkinsfile documentation adds that pipelines using trusted credentials can disclose them, so untrusted jobs should not be allowed to use them. It also says log masking only prevents accidents.

How do you separate trusted from untrusted builds?

Think in two lanes.

The first lane is untrusted: pull requests from forks and from contributors you do not know. These builds should compile and run tests with no credentials at all. No deploy keys, no registry push tokens, no cloud roles.

The second lane is trusted: builds of branches that have already been reviewed and merged. Only these should bind credentials, and only inside the stage that needs them.

How you split the lanes depends on your branch source plugin. Check its documentation for how it decides whether to trust a pull request, and test the behavior with a throwaway fork before you rely on it. We did not verify plugin specific settings for this post, so confirm them in your version.

What about the Jenkinsfile itself?

A pull request that edits the Jenkinsfile is the sharpest case. Ask whether your job takes the pipeline definition from the proposed change or from the trusted base branch. If it takes it from the change, the author controls the whole build. Using the definition from a trusted branch for untrusted changes limits what they can alter, though the build scripts they call can still change.

Also check agents. A build agent that serves both lanes can keep files, caches and processes between jobs. Use fresh or dedicated agents for the untrusted lane.

What to do

  1. Set the number of executors on the built-in node to zero, and build on agents.
  2. Split jobs into an untrusted lane with no credentials and a trusted lane that binds them.
  3. Review who can open builds from forks, and require approval for unknown contributors where your plugin supports it.
  4. Bind credentials per stage, never at the top of the pipeline.
  5. Use dedicated or ephemeral agents for pull request builds.
  6. Treat environment variables and parameters as input, and quote them in scripts.
  7. Rotate any credential an untrusted build could have seen.

Safeguard's pull request gate can block a change that adds a vulnerable or suspicious dependency before merge. See the pull request gate demo.

Quick check

Can a pull request steal credentials without touching Jenkins settings?

Yes, if the job runs the author's code and binds credentials for that build. The code runs with the job's access, so keep credentials out of untrusted builds.

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.