Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022 | Azure DevOps Server 2020
To protect the code that runs their operations, organizations must carefully control access to their source code repositories. This article describes how Azure Pipelines build and release pipelines can securely access repositories to minimize the risk of unauthorized access.
This article is part of a series that helps you implement security measures for Azure Pipelines. For more information, see Secure Azure Pipelines.
Prerequisites
| Category | Requirements |
|---|---|
| Azure DevOps | - Implement recommendations in Make your Azure DevOps secure and Secure Azure Pipelines. - Basic knowledge of YAML and Azure Pipelines. For more information, see Create your first pipeline. |
| Permissions | - To modify pipelines permissions: Member of the Project Administrators group. - To modify organization permissions: Member of the Project Collection Administrators group. |
Project-based identities for pipelines
A pipeline uses an identity to access resources such as repositories, service connections, and variable groups during execution. Pipelines can utilize two types of identities: collection-level or project-level.
Collection-level identity is easy to set up and use, but project-level identities prioritize security. To enhance security, use project-level identities to run pipelines. A project-level identity can access resources only within its project, minimizing the impact of any unauthorized access by malicious actors. For more information, see Scoped build identities and Job authorization scope.
To configure a pipeline to use a project-level identity, you enable Limit job authorization scope to current project for non-release pipelines or Limit job authorization scope to current project for release pipelines in the pipeline project's Project Settings under Pipelines > Settings.
Steps to improve repository access security
A Project Administrator or Project Collection Administrator can take the following steps to improve security for accessing Git repositories from pipelines.
Inspect the pipelines to identify any required repositories that are in other projects. If you enable Limit job authorization scope to current project for non-release pipelines, pipelines can check out code only from the current project's repositories.
Grant pipeline projects access to any other projects they require. For more information, see Configure permissions for a project to access another project in the same project collection.
Grant pipeline build identities Read access to each repository they check out. Also grant pipeline identities Read access to any repositories used as submodules by required repositories. For more information, see Configure permissions to access another repo in the same project collection.
Enable the following organization or project settings for the pipeline project:
- Limit job authorization scope to current project for non-release pipelines.
- Limit job authorization scope to current project for release pipelines if your project has release pipelines.
- Protect access to repositories in YAML pipelines if your project has Azure Repos YAML pipelines.
Enable these settings by setting their toggles to On in Organization Settings or Project Settings > Pipelines > Settings > General.
If the settings are enabled in Organization Settings, they can't be overridden in Project Settings. If the settings aren't enabled in Organization Settings, they can be enabled at the project level.
Use a repository as a submodule
If a repository uses another repository in its project as a submodule, checkout can fail when checking out the submodule even if you grant the pipeline Read access to both repositories. To solve this issue, explicitly check out submodule repositories before checking out the repositories that use them. For more information, see Check out submodules.
GitHub repositories
The following security considerations apply for pipeline access to GitHub repositories. For more information, see Access to GitHub repositories.
GitHub service connections
To use GitHub repositories, Azure Pipelines requires a GitHub service connection. To strengthen service connection security:
- Allow access only to repositories that pipelines require to run.
- Don't select Grant access permission to all pipelines for the service connection. Explicitly authorize the service connection for each pipeline that uses it.
Authentication to GitHub repositories
To trigger builds and fetch code during builds, Azure Pipelines must be granted access to GitHub repositories. This access can use GitHub personal access token (PAT), OAuth, or GitHub Azure Pipelines app authentication. For more information, see Access to GitHub repositories.
The GitHub Azure Pipelines app is the recommended authentication type for continuous integration (CI) pipelines. Builds and GitHub status updates then use the Azure Pipelines identity instead of using your personal GitHub identity. When you install the app, you can limit which repositories the app can access for increased security.
OAuth and PAT authentication use your personal GitHub identity and must be authorized for pipeline access. Using a PAT is discouraged due to security concerns. If you must use PAT authentication, choose a fine-grained PAT and limit the scope to certain users, repositories, and permissions. For more information, see Managing your personal access tokens.
Note
If you install the GitHub app for all repositories in a GitHub organization, the token the app uses can access all private and public repos in the organization. For better security, either separate private repos into a separate organization, or explicitly select which repositories the app can access.
Forked GitHub repositories
Forked repositories increase the risks of malicious code execution or sensitive information release in pipelines. Forks originating from outside your organization pose particular risks.
To minimize risks from forked repositories, Limit building pull requests from forked GitHub repositories and Disable building pull requests from forked repositories are enabled by default in Project Settings or Organization Settings > Pipelines > Settings > Triggers.
To allow building from forked GitHub repositories but reduce the risks, select Securely build pull requests from forked repositories. This setting disallows making secrets available or using the same permissions as normal builds, and requires a PR comment from a team member to trigger the pipeline.
Alternatively, you can select Customize rules for building pull requests from forked repositories to further customize these settings.
Other ways to increase fork security include:
If you use pull request validation to trigger builds, deselect Build pull requests from forks of this repository in the Trigger section of the pipeline definition, or ensure that Make secrets available to builds of forks and Make fork builds have the same permissions as regular builds are deselected. You can also select Require a team member's comment before building a pull request.
Use Microsoft-hosted agents to build from forks. Resources are then immediately deleted from the agents after builds. If you use self-hosted agents, clean and update the agents regularly, or use separate agents for different forks or branches.
Azure Repos repositories
Protect access to repositories in YAML pipelines
The Protect access to repositories in YAML pipelines project or organization setting provides fine-grained permissions for YAML pipelines. This setting makes a YAML pipeline explicitly request permission to access any repository, regardless of project. For more information, see Protect access to repositories in YAML pipelines.
Note
The Protect access to repositories in YAML pipelines setting doesn't apply to GitHub repositories.
When this setting is enabled, Azure Repos YAML pipelines always request permission to access repositories the first time they run. You see a permission request like the following screenshot:
Select Permit to grant permission to your pipeline repositories or resources. The pipeline now succeeds.
Use a git command line to check out other repositories
A command-line script like git clone https://github/fabrikam-tailspin/FabrikamFiber/_git/OtherRepo/ can fail when Protect access to repositories in YAML pipelines is enabled. To solve the issue, explicitly check out the OtherRepo repository using the checkout command, such as checkout: git://FabrikamFiber/OtherRepo.
Azure Repos example
The following example illustrates the process of improving security for Azure Repos access in a pipeline.
The https://dev.azure.com/fabrikam-tailspin organization contains the SpaceGameWeb and FabrikamFiber projects.
The SpaceGameWeb project contains the SpaceGameWeb and SpaceGameWebReact repositories.
The FabrikamFiber project contains the FabrikamFiber, FabrikamChat, and FabrikamFiberLib repositories. The FabrikamFiber repository uses the FabrikamFiberLib repository as a submodule.
The SpaceGameWeb pipeline in the SpaceGameWeb project checks out the SpaceGameWebReact repo in the SpaceGameWeb project and the FabrikamFiber and FabrikamChat repos in the FabrikamFiber project.
If the project isn't set up to use a project-based build identity or to protect access to repositories in YAML pipelines, the SpaceGameWeb pipeline can access all repositories in all projects in the organization and runs successfully.
Use project-level identity
To improve security, use a project-level identity to run the pipeline. Enable the Limit job authorization scope to current project for non-release pipelines toggle in Project Settings or Organization Settings.
If this setting is enabled, the pipeline can only access resources in the SpaceGameWeb project, which contains only the SpaceGameWeb and SpaceGameWebReact repositories. The pipeline fails because it can't check out the repositories in the FabrikamFiber project.
You see the errors remote: TF401019: The Git repository with name or identifier FabrikamChat does not exist or you do not have permissions for the operation you are attempting and remote: TF401019: The Git repository with name or identifier FabrikamFiber does not exist or you do not have permissions for the operation you are attempting.
To fix the issues, grant the pipeline project access to the FabrikamFiber project, and grant the pipeline identity Read access to the FabrikamFiber, FabrikamChat, and FabrikamFiberLib repositories.
Explicitly check out the submodule
The FabrikamFiber repository uses the FabrikamFiberLib repository as a submodule. Even if you give the pipeline access to both repositories, the FabrikamFiber repository checkout still fails when checking out the FabrikamFiberLib submodule.
To fix this issue, explicitly check out the FabrikamFiberLib repository before you check out the FabrikamFiber repository. Add a checkout: git://FabrikamFiber/FabrikamFiberLib step before the checkout: FabrikamFiber step. The example pipeline now succeeds.
Protect access to the YAML pipeline
If the example SpaceGameWeb pipeline is a YAML pipeline, and Protect access to repositories in YAML pipelines is enabled, the pipeline requires permission to access the SpaceGameWebReact, FabrikamFiber, and FabrikamChat repositories the first time it runs.
The following code shows the full YAML pipeline.
trigger:
- main
pool:
vmImage: ubuntu-latest
resources:
repositories:
- repository: SpaceGameWebReact
name: SpaceGameWeb/SpaceGameWebReact
type: git
- repository: FabrikamFiber
name: FabrikamFiber/FabrikamFiber
type: git
- repository: FabrikamChat
name: FabrikamFiber/FabrikamChat
type: git
steps:
- script: echo "Building SpaceGameWeb"
- checkout: SpaceGameWebReact
- checkout: FabrikamChat
condition: always()
- checkout: git://FabrikamFiber/FabrikamFiberLib
- checkout: FabrikamFiber
submodules: true
condition: always()
- script: |
cd FabrikamFiber
git -c http.extraheader="AUTHORIZATION: bearer $(System.AccessToken)" submodule update --recursive --remote
- script: cat $(Build.Repository.LocalPath)/FabrikamFiber/FabrikamFiberLib/README.md
More repository security measures
To reduce security risks from YAML and Classic pipelines sharing resources, disable creation of classic pipelines by turning on the Disable creation of classic build pipelines and Disable creation of classic release pipelines toggles in Project Settings or Organization Settings. Classic build and release pipeline creation are disabled by default for new organizations.
Use pipeline templates to define the pipeline structure and help prevent malicious code infiltration. Templates can also automatically do tasks such as credential scanning or enforcing checks on protected resources.
Require manual approval each time a pipeline requests the repository. For more information, see Approvals and checks.
Use a protected branch check to prevent pipelines from automatically running on unauthorized branches.
Set a repository to be used only in specified YAML pipelines. For more information, see Add pipeline permissions to a repository resource.
Limit the scope of the Azure Pipelines access token by providing the token only for repositories listed in the pipeline's
resourcessection. For more information, see Repository protection.