I'm slightly confused by the description on this page. I understand how a template can sanitize its parameters. But: how can I ensure that the azure-pipelines.yml actually uses that template and users cannot add arbitrary commands to the azure-pipelines.yml file in a pull request?
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
Ha. I had the same question in my mind while reading this.
Let's say my template.yml file has a deployment job to production requiring an environment with approvals. In azure-pipelines.yml file I can reference template.yml using extends, but there doesn't seem to be anything stopping someone else just removing the extends and putting in their own steps or using their own malicious template.yml file in extends without environment approvals.
Interesting, my thoughts exactly. Extending xenalite example - lets assume the aure-pipelines.yml that is meant to deploy to production, uses a service connection to prod. By leveraging template extension in azure-pipelines.yml we could force to run from specific branch (lets say prod). But since the pipeline is tied to repo not a branch, what would stop anyone from running that pipeline from another branch where the template was not mentioned at all in aure-pipelines.yml and hence the branch was not enforced? In consequence someone could deploy to prod from a dev branch. Are we missing out on something here?
Ah, it seems that the documentation was quicker than the deployment of new features.
Now you can enforce the use of a specific template for a given runner if you go to
There might be more ways of doing it, but this seems to work now. Can this information be added to the docs?
Edit: Unfortunately, even though the interface is there, it doesn't seem to work; whatever I enter as requirements, the job is always auto-cancelled with no further information whatsoever. I've opened #7476 to learn more about how this feature is supposed to be used. (Before I open an issue that it doesn't work :smile:)
I've got it to work when the root pipeline extends from a template, and this example itself accepts other templates as parameters (it's a design pattern we're wanting to enforce for higher security):
Master template
parameters:
- name: templates
type: object
default: []
stages:
- ${{ each template in parameters.templates }}:
- ${{ each pair in template }}:
${{ if eq(pair.key, 'template') }}:
${{ template }}
Root pipeline with extends
trigger:
- *
resources:
repositories:
- repository: template_reference
type: git
name: name_of_template_repo
ref: "refs/heads/master"
extends:
template: templates/master.yml@template_reference
parameters:
templates:
- template: ../path/in/template/repo/to_file.yml
parameters:
my_param_1: "my value 1"
my_param_2: "my value 2"
Check is shown on the pipeline

Check has been set up on the agent pool (thanks @imphil for finding this)

Seemingly good news.
If the root pipeline has something with malicious intent like this with no reference to a template, the check is completely ignored
trigger:
- *
steps:
- bash: |
file_path=$(Build.ArtifactStagingDirectory)/env.txt
env > ${file_path}
cat ${file_path} # echo to log
name: get_drop
# Allow file to be downloaded
- task: PublishPipelineArtifact@1
inputs:
artifactName: 'drop'
targetPath: '$(Build.ArtifactStagingDirectory)'
displayName: publish_drop
name: publish_drop
Which allowed the environment variables to be "echoed" out to the log and also published as an artifact for download, notice how no checks were performed whatsoever.

This is particularly worrisome as we:
git push to fork feature branches (no deployment steps are allowed to perform off a fork, PRs into upstream must occur for those)azure-pipelines.yml root files from being modified, or for the checks against to actually fire every time regardless of the state of the root azure-pipelines.yml file.Is there a fix or workaround published somewhere?
Not sure why this ticket got closed with no explanation...
@adriantorrie You could set a policy on the git repo itself to prevent modifications to root file once it was created?

Most helpful comment
Interesting, my thoughts exactly. Extending xenalite example - lets assume the
aure-pipelines.ymlthat is meant to deploy to production, uses a service connection to prod. By leveraging template extension inazure-pipelines.ymlwe could force to run from specific branch (lets say prod). But since the pipeline is tied to repo not a branch, what would stop anyone from running that pipeline from another branch where the template was not mentioned at all inaure-pipelines.ymland hence the branch was not enforced? In consequence someone could deploy to prod from a dev branch. Are we missing out on something here?