A merge request pipeline can use protected variables and protected runners when both the source and target branches are protected, the person who triggered it has push or merge access to the target branch, and both branches are in the same project. Pipelines from forks never get them. A project Maintainer can switch the behavior off.
The three conditions
GitLab's merge request pipeline documentation lists them directly. All must be true.
| Condition | What it blocks |
|---|---|
| Source and target branches are both protected | Ordinary feature branches |
| Triggering user can push or merge to the target | Contributors without rights |
| Both branches live in the same project | Fork merge requests |
If any one fails, protected variables are not injected, and a job that needs one will usually fail or run with an empty value.
What a merge request pipeline actually tests
These pipelines run on the contents of the source branch and ignore the target branch. They start when you open a merge request from a branch with commits, push to the source branch, or press Run pipeline on the merge request. To get them, rules in .gitlab-ci.yml must match merge_request_event. Rules that arrive through include do not count for this purpose, so write the matching rule in the main file.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
If you want to test the combined result of source and target, GitLab offers merged results pipelines, which test a temporary merged commit. They need the Maintainer or Owner role to enable and a project hosted on GitLab.
Forks are different
A merge request from a fork runs in the fork, with the fork's configuration, runners and variables. A parent project member can trigger a pipeline in the parent instead, which uses the parent's runners and variables with the fork's branch configuration. GitLab warns that fork code may try to steal parent secrets, so review the changes first. Our post on fork merge request pipelines and secret safety covers that decision.
Steps to check your own setup
- Open Settings, CI/CD, Variables and note which variables are marked protected.
- Check that your default and release branches are protected. See protected branches setup.
- Review who has push or merge rights on those branches.
- Decide whether merge request pipelines should see protected variables at all. A test job rarely needs a deploy key.
- Keep deploy secrets in jobs that only run on the protected branch after merge.
Try it yourself
Click through it at your own pace, or open it full screen. Watch where the gate sits relative to the merge, since that is where a check should block.
Safeguard policies and gates can block a merge when a pull or merge request introduces a finding, and you can try a free scan at https://gold.safeguard.sh/scan.
Quick check
Why not give every pipeline the variables?
A branch pipeline runs code from whoever pushed it. Protected variables limit secrets to code that passed review.
Does masking replace protection?
No. GitLab says masking is not a guaranteed way to stop a malicious user from reading a value.
Sources
- GitLab Docs: Merge request pipelines, fetched 19 October 2026.
- GitLab Docs: Merged results pipelines, fetched 19 October 2026.
- GitLab Docs: CI/CD variables, fetched 19 October 2026.
Last reviewed: 19 October 2026.