Safeguard
Cloud Security

Preventing and detecting Azure service principal credenti...

How Azure service principal secrets leak through repos, pipelines, and IaC state files — and the detection, scoping, and rotation practices that stop a leak from becoming a breach.

Karan Patel
Cloud Security Engineer
7 min read

Every Azure service principal has a secret behind it, and that secret is often the weakest link between a developer's laptop and your production subscription. In March 2023, GitGuardian's annual State of Secrets Sprawl report found that public GitHub commits alone exposed over 12.7 million secrets, and Azure client secrets consistently rank among the most common cloud credential types found in the wild. An Azure service principal secret leak doesn't require a sophisticated exploit — it usually starts with a secret pasted into a CI/CD YAML file, a config committed to a public repo, or a Terraform state file left in an unsecured S3 bucket. Once exposed, that single string of characters can grant an attacker the same programmatic access to your subscription that your automation pipelines have — often with far more standing privilege than anyone intended. This post breaks down how these leaks happen, how to catch them fast, and how to stop granting attackers a free pass in the first place.

What Is an Azure Service Principal Secret Leak?

An Azure service principal secret leak occurs when the client secret tied to an app registration — the credential Azure AD (Entra ID) uses to authenticate non-human identities — ends up somewhere an attacker can read it. Service principals are how scripts, CI/CD pipelines, Terraform runs, and third-party SaaS integrations authenticate to Azure without a human logging in interactively. Each one can carry a client secret (a plaintext-equivalent string, valid for up to 24 months by Azure's default) or a certificate. Because these secrets are just text, they behave exactly like any other credential when handled carelessly: they get hardcoded into source, pasted into Slack threads for "just testing," embedded in Docker images, or dumped into environment variable exports that land in build logs. Microsoft's own August 2023 guidance around the Storm-0558 token-forging campaign underscored how much damage a single compromised signing credential in Azure's ecosystem can cause — and service principal secrets are a much more common, much less exotic version of the same problem.

How Do Azure Service Principal Secrets Actually Get Exposed?

They leak through the same handful of channels, over and over, because those channels are convenient. The top four sources we see across incident response engagements are: (1) secrets committed directly into Git repositories — including private repos that later get made public or forked; (2) CI/CD pipeline definitions (GitHub Actions, Azure DevOps YAML, GitLab CI) where a secret is set as a plaintext variable instead of a pipeline secret; (3) infrastructure-as-code state files, particularly Terraform .tfstate, which store resource attributes — including secrets — in plaintext JSON by default; and (4) client-side or container image layers, where a .env file or appsettings.json gets baked into a Docker image that's later pushed to a public registry. A 2023 analysis by Datadog's security research team found that over 60% of organizations had at least one long-lived cloud credential with no rotation policy — and Azure client secrets, which don't require rotation to keep functioning, are prime candidates for this kind of silent, years-long exposure.

What Are the Service Principal Security Risks Once a Secret Is Public?

The core service principal security risk is that the credential is bearer-token equivalent — whoever holds it can act as that identity, immediately, from anywhere, with no MFA challenge. Unlike a leaked user password, there's no second factor standing between an attacker and your Azure resources. If the service principal was scoped broadly (Contributor or Owner at the subscription level, which is unfortunately common because it's the path of least resistance during setup), a leaked secret can let an attacker enumerate resources, exfiltrate data from storage accounts and Key Vaults, spin up expensive compute for cryptomining, or pivot into connected systems like Azure SQL and AKS clusters. The blast radius scales directly with over-provisioned permissions — a service principal scoped to a single resource group with read-only access limits the damage from a leak to that resource group, while a subscription-wide Owner-scoped principal turns one leaked secret into a full tenant compromise. This is why least-privilege scoping for every app registration matters as much as protecting the secret itself.

How Can You Detect Exposed Azure Credentials Before Attackers Do?

You detect exposed Azure credentials by scanning every place a secret could plausibly land — not just your primary application repos. That means continuous secret scanning across source code (including commit history, not just the current HEAD), CI/CD logs and pipeline variable definitions, container images and registries, IaC state files, and even internal chat and ticketing systems where developers paste config for troubleshooting. Speed matters enormously here: GitHub's own secret-scanning partner program typically notifies cloud providers within seconds of a matching pattern hitting a public repo, and Microsoft's equivalent Azure AD credential-scanning service revokes many detected public-repo secrets automatically. But that safety net only covers public GitHub — it does nothing for secrets leaked in private repos, internal Jenkins logs, Slack, or a colleague's laptop. Organizations that rely solely on the public-GitHub safety net routinely miss leaks sitting in private infrastructure for months. Effective detection requires audit-log correlation too: unusual sign-in locations, impossible-travel patterns, or a service principal suddenly authenticating from an ASN it's never used before are strong signals a secret has already left your control, even before you find the leaked string itself.

Certificate vs Secret Authentication Azure: Which Should You Use?

For any service principal that supports it, certificate-based authentication is the safer default over a client secret. When comparing certificate vs secret authentication in Azure, the practical difference comes down to how the private key is handled: a client secret is a plaintext string that can be copy-pasted, logged, or displayed in a terminal, while a certificate's private key can be generated and stored in a hardware- or software-backed store (like Azure Key Vault with a non-exportable key) and never needs to touch a config file at all. Certificates also tend to carry stronger cryptographic guarantees and are harder to accidentally paste into a Slack message. That said, certificates aren't a silver bullet — a certificate file copied into a repo is just as exposed as a secret string, and certificate expiry management adds operational overhead many teams aren't set up for. The more durable fix, where your workload supports it, is Azure Workload Identity Federation, which eliminates the stored credential entirely by letting GitHub Actions, Kubernetes, or other OIDC-capable platforms exchange a short-lived token directly for Azure access — no secret or certificate to leak in the first place.

How Do You Prevent an Azure Service Principal Secret Leak From Happening Again?

Prevention comes down to shortening secret lifetimes, narrowing scope, and removing humans from the credential-handling loop. Concretely: set client secret expiration to 90 days or less (Azure allows up to 24 months by default, which is far too long), enforce Conditional Access policies that restrict service principal sign-ins to known IP ranges where possible, and migrate CI/CD pipelines to workload identity federation so there's no secret to rotate at all. Every app registration should be scoped with least-privilege role assignments at the resource-group level rather than subscription-wide Owner or Contributor roles — a 2024 review of misconfigured Azure tenants found that a majority of app registrations audited held broader permissions than their actual workload required. Pair this with pre-commit hooks and CI-stage secret scanning so leaked credentials are caught before a commit ever reaches a shared branch, and set up automated revocation playbooks so that when a leak is confirmed, the secret can be killed within minutes, not days.

How Safeguard Helps

Safeguard continuously scans your source repositories, CI/CD pipeline configurations, container images, and IaC state files for exposed Azure service principal secrets, API keys, and certificates — across public and private repos alike, not just the surface GitHub's own scanner covers. When a credential is found, Safeguard correlates it against Azure AD sign-in logs to flag whether it's already been used from an unexpected location, giving your team a real signal about active compromise rather than just a hygiene finding. Beyond detection, Safeguard's policy engine flags over-privileged app registrations, secrets nearing or exceeding safe expiration windows, and pipelines still using static secrets where workload identity federation is available — turning "we think we might have a leaked credential somewhere" into a prioritized, actionable list your team can close out before an attacker finds it first.

Never miss an update

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