Safeguard
Application Security•

What is the safest way to handle secrets in Azure Pipelines?

Avoid secrets where you can, use service connections and managed identities, keep the rest in Key Vault or locked variable groups, and limit to one branch.

Safeguard Security Team
5 min read

The safest secret in Azure Pipelines is the one you never create. Use service connections and managed identities where possible, keep what remains in Azure Key Vault or a permissioned variable group, never pass secrets on the command line, and restrict them to pipelines on a designated branch.

Why does Microsoft say to avoid secrets entirely?

Microsoft's own guidance on secrets in Azure Pipelines starts there: secrets carry inherent risk, so first check whether the pipeline can do the task another way. It names three options. Service connections connect safely to Azure or to services such as GitHub and Docker. Managed identities let applications authenticate to Azure services without explicit credentials. And the Azure CLI task with the addSpnToEnvironment option exposes service principal details without you passing secrets around.

Every secret you remove is one fewer value to rotate, leak into a log, or find in a former employee's export.

Where should the remaining secrets live?

The guidance says never to store sensitive values as plain text in azure-pipelines.yml. Secret variables are encrypted, and Microsoft calls Azure Key Vault the best place to manage them. There are three storage choices with different access models:

  • Azure Key Vault, where Azure role-based access control limits who can read a secret or a group of secrets.
  • Secret variables set in the pipeline UI, scoped to that pipeline and visible only to its users.
  • Variable groups, which follow the library security model so you can control who can access or create items.

Pick the narrowest one that works. A secret set on one pipeline cannot be borrowed by another.

Does log scrubbing protect you?

Microsoft states that Azure Pipelines attempts to scrub secrets from logs but is not foolproof. Three habits follow from that. Never echo a secret. Do not pass a secret as a command line argument, and map it into an environment variable instead. And do not set a secret variable through a logging command, since anyone who can access your pipeline can see it.

There is a less obvious rule about structure. Avoid wrapping secrets in JSON, XML or YAML, including control characters such as carriage returns, because redaction works better on individual values. Create one secret per sensitive value. Be careful with Azure CLI commands that output sensitive data, and use the None output format.

How do you keep a secret away from other branches?

The documentation describes a three part pattern. Enforce build validation policies that allow builds only from a certain branch. Use variable group permissions so only authorized pipelines can use the group. Then add a condition in the pipeline so that only a push to the designated branch can reference the variable group. A constructed case: a production variable group is permitted to one pipeline, and the deploy job carries a condition that checks the source branch is main. A feature branch run never gets the group.

What about templates and audits?

Instead of inline scripts that take secret parameters, the guidance recommends YAML templates stored in a separate, secure repository, with the secret passed in as a parameter from Key Vault, a variable group or the pipeline UI. For audits, read the repository that hosts the pipeline and check every task it uses, confirm secrets are not sent to unintended hosts, and review run logs after testing valid and invalid inputs, since errors in tools can leak values into error output. Keep personal access token lifetimes short with minimal permissions, remove registered secrets that are no longer needed, and rotate regularly.

What to do

  1. Inventory secrets in pipelines, variable groups and service connections, and delete unused ones.
  2. Replace secrets with service connections or managed identities wherever the target supports them.
  3. Move the rest into Key Vault with role-based access, one vault per application and environment.
  4. Map secrets to environment variables and remove any use on command lines.
  5. Split structured secrets into individual values.
  6. Apply the branch pattern: build validation, variable group permissions and a branch condition.
  7. Review third party tasks before use, since a task runs with the secrets you give it.
  8. Rotate on a schedule and shorten PAT lifetimes.

Try the same idea for repositories in the secrets scanning demo.

Quick check

Is a secret variable safe to print in a debug step?

No. Scrubbing is best effort and not foolproof, and echoing a secret can expose it in logs or through modified output.

Why prefer a managed identity over a stored password?

There is no credential to store, copy, leak or rotate. The platform issues access to the identity on demand.

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.