Preventing leakage of sensitive information
Design pipelines to prevent leakage of sensitive information
Masking is a safety net, not a control
Azure Pipelines masks registered secret values in logs, but transformed or encoded values are not masked automatically. If a job derives another sensitive value, register it with ##vso[task.setsecret]value before any possible output. Only subsequent occurrences are masked; earlier output remains exposed.
The safest design is still never to print either the original or transformed value.
Where leaks actually come from
| Source | Mitigation |
|---|---|
echo / set -x / verbose task logging | Never print secrets; avoid debug logging in jobs that hold them |
| Secrets passed as command-line arguments | Use deliberately mapped environment variables; arguments can appear in process listings and logs |
| Pull-request validation builds from forks of a public GitHub repository | Secrets and protected resources are not exposed by default; do not disable that protection |
| Nonsecret variable-group values | Masking is not guaranteed. Unlike secret variables, their access is not limited by approvals, checks, or pipeline permissions |
| Committed configuration | Revoke or rotate the credential first; removal from the current tree does not remove it from history, clones, or forks |
| Error messages and stack traces | Treat connection strings and other embedded credentials as leaks |
Explicit mapping
Secret variables are not automatically exported as environment variables for scripts. Map them deliberately only into the step that needs them:
- script: ./deploy.sh
env:
API_KEY: $(apiKey)That friction makes the set of steps able to receive a secret explicit and reviewable. Avoid passing secrets on the command line.
Least exposure
Explicit mapping and restrained logging reduce exposure probability. Least-privilege resource scope limits blast radius.
Where possible, remove the stored credential. Workload identity federation exchanges a trusted external-provider token for an access token without storing a long-lived secret. For suitable Azure-hosted workloads, managed identities obtain Microsoft Entra tokens without developer-managed credentials.
Primary sources
- https://learn.microsoft.com/en-us/credentials/certifications/resources/study-guides/az-400
- https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops
- https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops
- https://learn.microsoft.com/en-us/azure/devops/pipelines/library/variable-groups
- https://learn.microsoft.com/en-us/azure/devops/pipelines/security/overview?view=azure-devops
- https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation
- https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview
- https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository