Cloud Security

Azure DevOps Supply Chain Hardening Guide

A senior engineer's 2026 playbook for hardening Azure DevOps against the supply chain attacks that actually happen: extensions, service connections, and template injection.

Shadab Khan
Security Engineer
7 min read

Azure DevOps is the CI/CD that every Microsoft-shop security team has to defend whether they like it or not. The platform has shipped meaningful improvements in the last two years — federated identity, workload identity federation, and stronger pipeline-level approvals — but the default configuration is still generous in ways that produce incidents. If you are running Azure DevOps in 2026, the work is not to move off it; the work is to catch up with the security primitives Microsoft has already shipped and to close the gaps they have not.

This guide is the compressed version of the hardening conversations I have had with a dozen platform teams over the last year. The controls are ordered roughly by impact per hour of engineering effort.

Why does Azure DevOps still feel less secure than its competitors by default?

Because its defaults are calibrated for broad enterprise adoption, and enterprise adoption has historically preferred convenience to least privilege. A freshly provisioned Azure DevOps organization lets any project administrator install marketplace extensions, create service connections with contributor-level scopes, and run pipelines on pull requests from forks with the same secrets as internal branches. None of those defaults are obviously wrong until you see what an attacker can do with them.

The other reason is history. Azure DevOps is the descendant of VSTS, which was the descendant of Team Foundation Server. Some of the trust model inherited from TFS — in particular, the notion that anyone inside the organization is reasonably trusted — does not survive contact with a modern threat model. Microsoft has fixed many of these, but the fixes are opt-in, and most customers have not opted in.

The good news: every major risk in Azure DevOps now has a Microsoft-native control. The bad news: turning them on requires a deliberate hardening pass, because the defaults will not change for customers who have been running for years.

How do I lock down marketplace extensions without blocking engineering?

Turn on the extension management policy, require administrator approval for new installs, and audit installed extensions against a trust list monthly. That is the baseline. The tighter version is to disallow extension installs entirely at the organization level and maintain a vetted shortlist in a shared project that other projects can request additions to.

Extensions are the part of Azure DevOps that gives me the most pause, because they run with the permissions of whoever installed them and can call the full Azure DevOps API. A malicious extension update can exfiltrate build secrets, modify pipeline definitions, and create new service connections pointing at attacker-controlled infrastructure. The marketplace has basic publisher verification, but publisher verification is not a code review.

The control that works is a quarterly extension audit. List every installed extension, the publisher, the last update date, the permissions claimed, and compare against the list from the previous quarter. Any new extension gets a one-page review before it stays. Any unused extension gets removed. This is boring, and it is the most effective single control against extension-based attacks.

How should I use workload identity federation for Azure subscriptions?

Use workload identity federation with federated credentials scoped to a single pipeline and environment, and delete every azurerm service connection that uses a client secret. Workload identity federation finally gave Azure DevOps what GitHub Actions had for two years — OIDC-based authentication to Azure with no long-lived secret on the CI side. It has been generally available long enough that there is no remaining excuse to run pipelines with service principal secrets.

The scoping is the part that matters. A federated credential on a Microsoft Entra application can be limited to a specific subject, which for Azure DevOps is the combination of organization, project, pipeline, and optionally environment. Do not use the org-wide subject. Do not even use the project-wide subject. Use sc://org/project/pipeline:environment:production and make the credential valid only for that production deploy pipeline. When an attacker compromises a different pipeline in the same project, the federated credential does not grant them access to the production subscription.

The migration path from secret-based service connections is not painful. Azure DevOps has had an in-place converter for over a year. The thing that makes it painful is discovering how many existing pipelines depend on an overly broad service connection and refactoring them into properly scoped credentials. Plan for two sprints per large project.

What does safe pipeline-as-code look like in Azure DevOps?

Pipelines are defined in YAML in the repo, templates come from a protected internal feed, variable groups are scoped per environment, and pull requests from forks never touch production secrets. That is the short version. The long version is that Azure DevOps has three separate concepts — templates, variable groups, and environments — that together form the "who can change this pipeline's behavior" trust boundary, and all three need to be locked down.

Templates are the first class of attack. A pipeline can reference a template from another repository, and if that reference is a branch name rather than a fixed commit SHA, an attacker who compromises the template repo can inject arbitrary steps into every pipeline that references it. Always reference templates by SHA in production, and treat the template repo as a critical asset.

Variable groups with the "Link to Key Vault" option are the correct pattern for secrets. Inline variables in the pipeline YAML or the variable group UI are the wrong pattern because they are readable by anyone with project contributor access. Azure Key Vault integration gives you RBAC on the secret, audit logs on access, and rotation without touching the pipeline.

Environments are where pipeline approvals live. Configure the production environment with a required approval from the on-call engineer, a business-hours restriction, and a branch filter that only allows deployments from the protected main branch. This blocks the most common insider-threat scenario: someone triggering a deploy from a feature branch at 11 p.m. with no second pair of eyes.

How do I protect against malicious pull requests from forks?

Disable automatic fork builds, require the "Build pull requests from forks of this repository" setting to be off, and only enable it for specific repos behind a human-in-the-loop gate. This is the single setting that causes the most embarrassment when it is wrong.

If you must run builds on fork PRs — which some open source projects do — use a scoped pipeline with no access to variable groups, no access to service connections, and a read-only project role. Azure DevOps supports pipeline-level settings for "Make secrets available to pull requests" and "Require a comment to build pull requests." Both of these should be on for any pipeline that touches fork PRs. The comment requirement adds a human checkpoint, which sounds trivial until you realize that it blocks the PR-to-RCE attack entirely in most common cases.

How Safeguard.sh Helps

Safeguard.sh ingests Azure DevOps pipeline telemetry and applies reachability analysis to every artifact the pipelines produce, so you spend engineering time on vulnerabilities that are actually called by deployed workloads rather than on the long tail — reachability cuts 60 to 80 percent of findings that would otherwise land in the security team's queue. Griffin AI generates hardened YAML templates, workload-identity-federation configurations, and environment approval policies from your existing pipeline graph and detects drift when someone changes them in the UI. Safeguard's SBOM module attaches a signed SBOM to every pipeline artifact at 100-level dependency depth, its TPRM module tracks the risk profile of every marketplace extension and external template the organization consumes, and container self-healing rewrites workload image references automatically when Azure DevOps publishes a patched image that resolves a reachable vulnerability upstream.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.