Workload Identity Checks: Service Principal Takeover, Credential Backdoors and Illicit Consent
13 posture checks on service principals, app registrations and service accounts, with the fix named for each.
On this page
- Overview
- Prerequisites
- The checks
- Tenant takeover
- Credentials
- Disabled apps and OAuth consent
- Owners
- Peers and dormancy
- Active Directory
- Result states
- Not assessed
- Assessed N of M
- Step-by-step
- View workload identity findings
- Read the finding drawer
- Respond to a vendor app compromise
- Remove a tenant-takeover permission or an admin role
- Fix everything else in Microsoft Entra
- Configuration
- Troubleshooting
- A check reads "Not assessed" and says "Collected at the next Entra sync"
- Service principal has more permissions than its peers reads "Not assessed"
- Dormant service principal is still privileged reads "Not assessed"
- A check reads "Assessed N of M"
- An app I expected to flag doesn't appear
- I removed a permission and the finding is still there
Overview
The Workload and agent identity category on the Security Posture page (Exposure > Security Posture) checks the identities that act without a person: Microsoft Entra service principals, the app registrations behind them, and Active Directory service accounts. An attacker who steals one app credential, or adds one, acts as that app. Nothing prompts for MFA, and the app often holds more access than any user.
The checks cover five risks:
- an app that can take over the tenant, by permission or by admin role;
- a credential that shouldn't be there, or that lives too long;
- an app Microsoft disabled, or an OAuth grant nobody can account for;
- people who can add a credential to a privileged app, and apps nobody owns;
- an app that holds far more than its peers, or hasn't been used in a long time.
The checks run after each Entra ID sync, with nothing to turn on. Each failing check becomes a finding on the service principal, app registration or account. Every finding opens a drawer that shows who owns the app and why it matters.
Prerequisites
- Role: Operator or Admin to see findings and use Select Fire.
- Data: A synced Entra ID tenant. See Entra ID Manual Setup or Automated Entra ID Setup. One check runs on Active Directory instead and needs the Identity Bridge.
- Permissions: The permissions your Entra app registration already holds for the sync. The first Entra sync after an upgrade collects the extra data these checks read. See Not assessed.
- Admin roles and PIM: The two admin-role checks read role assignments, including roles that are eligible in Privileged Identity Management (PIM). The checks in Entra ID and Hybrid Checks use the same data.
The checks
Titles are as they appear on the Security Posture page.
Tenant takeover
| Title | Severity | What it checks |
|---|---|---|
| Service principal holds a tenant-takeover permission | Critical | An application permission leads to Global Administrator, directly or through another object such as an app, a group or a policy. |
| App service principal holds a Tier 0 admin role | Critical for a third-party app. High for your own app or an unknown owner. High for a Microsoft app, or Low when allowlisted. | An app's service principal holds a Tier 0 admin role such as Global Administrator, assigned or eligible in PIM. |
- Service principal holds a tenant-takeover permission covers permissions such as
RoleManagement.ReadWrite.DirectoryandDirectory.ReadWrite.All. The drawer lists each permission and whether it reaches Global Administrator directly, through another object, or only with a tenant setting turned on. A direct path adds a Can escalate to edge from the service principal to Global Administrator. It shows in the blast radius and in what-if simulations. Simulating removal of the permission removes the edge. - App service principal holds a Tier 0 admin role replaces the standing privileged role check for apps. A role held through a role-assignable group counts, and the drawer names the group. If PIM eligibility wasn't collected, the drawer says it shows active roles only.
- A Microsoft app on the built-in hybrid allowlist stays on the list at Low and never passes silently.
Credentials
| Title | Severity | What it checks |
|---|---|---|
| Credentials on a Microsoft first-party service principal | Critical. Low for allowlisted hybrid apps. | A credential was added in your tenant to the service principal of an app Microsoft publishes. |
| Credential added to a third-party app's service principal | Critical when the app is privileged, otherwise High. | A credential was added in your tenant to an app another organization owns, or whose owner Entra doesn't name. |
| Long-lived service principal credential | High | An app your organization owns has a secret valid for more than 12 months, a certificate valid for more than 24 months, or more than two active secrets. |
| Privileged service principal authenticates with a secret | Medium | A privileged app can sign in with a client secret. |
- A vendor's app keeps its credentials in the vendor's own tenant. A credential on its service principal in your tenant was added here, which is a common backdoor (MITRE ATT&CK T1098.001, Additional Cloud Credentials). An app whose owner Entra doesn't name is High.
- Long-lived service principal credential reads the app registration's credentials too. The drawer shows where each one is stored, and the limit it passed. Three active secrets at once fail the check even when each is short-lived, since one current secret plus one for rotation is the most an app needs.
- A privileged app is one that holds a tenant-takeover permission, any other application permission rated High or Critical, or a Tier 0 admin role. A delegated permission never makes an app privileged on its own.
Disabled apps and OAuth consent
| Title | Severity | What it checks |
|---|---|---|
| App disabled by Microsoft still holds permissions | High | Microsoft disabled the app for violating its services agreement, and its service principal still holds app role assignments or consent grants. |
| Illicit or over-consented OAuth grant | High for a tenant-wide grant. Medium when five or more users consented. | An app with an unverified publisher holds consent to sensitive data. |
- Illicit or over-consented OAuth grant (T1528, Steal Application Access Token) fails in two cases. A tenant-wide grant with a sensitive scope and
offline_accessis High. The same kind of scope consented by five or more individual users is Medium. Apps with a verified publisher are never flagged. If the publisher status isn't collected, the check reads Not assessed for that app. - A disabled app's permissions stay in place until someone removes them. The drawer counts the app role assignments and delegated grants, and lists the permission names.
Owners
| Title | Severity | What it checks |
|---|---|---|
| Non-privileged owner of a privileged app or service principal | High | Someone who isn't a Tier 0 administrator can add a credential to a privileged app, as its owner or through an admin role that manages app credentials. |
| Privileged app registration with no active owner | Medium | No enabled user or service principal owns the app registration, and its service principal is privileged. |
- Non-privileged owner covers owners of the app registration, owners of the service principal, and scoped credential admin roles. A tenant-wide Application Administrator counts as Tier 0, so it isn't a finding.
- No active owner lists owners that are disabled. An app with no owners at all fails too.
- Owners in another Entra tenant you've connected aren't read here. The drawer says so.
Peers and dormancy
| Title | Severity | What it checks |
|---|---|---|
| Service principal has more permissions than its peers | Medium | The service principal's permission weight is more than 2 standard deviations above the average of similar service principals in your tenant. |
| Dormant service principal is still privileged | Medium | A privileged app's service principal hasn't signed in for a long time. |
- Service principal has more permissions than its peers reads the over-permission analysis. It reads Not assessed until peer comparison has run for the connector. A service principal with no peers to compare, or outside every peer group, doesn't apply.
- Dormant service principal is still privileged reads Not assessed. It needs service principal sign-in activity, which the sync doesn't collect.
Active Directory
| Title | Severity | What it checks |
|---|---|---|
| Service account can log on interactively | Medium | An enabled service account with a service principal name has no Log On To restriction, so it can log on at any computer in the domain. |
Group managed service accounts are excluded. The bridge always collects the userWorkstations attribute that holds the Log On To list. See Identity Bridge. Until the bridge has synced the domain once, the check reads Not assessed.
Result states
Each check reads Passing, Failing, Not assessed or Doesn't apply, as on the other posture checks. Not assessed is never a pass.
Not assessed
The line under a Not assessed check names what's missing. The usual reasons:
- Collected at the next Entra sync. The first sync after an upgrade collects the publisher, disabled status and credential dates these checks read. Run Sync now on the tenant, or wait for the next sync.
- Peer comparison hasn't run for this connector yet. Service principal has more permissions than its peers needs the over-permission analysis to finish once.
- Service principal sign-in activity isn't available. Dormant service principal is still privileged has no sign-in data to read.
- Some app permissions, roles or registrations couldn't be resolved. The last Entra sync didn't finish reading them. The check assessed what it could and left the rest.
- PIM eligibility wasn't collected. The admin-role check can't say an app holds no eligible role.
- Workload identity data isn't collected yet. The connector hasn't collected the data the Active Directory check reads.
Assessed N of M
A check can read Assessed 41 of 52 accounts with a reason after it. It means GraphnAI checked 41 service principals or accounts and couldn't check 11. The 41 stand. A finding on any of them is real, and a pass on any of them is a pass. The 11 aren't counted as passing. Fix the reason named after the count, and the next run covers them.
Step-by-step
View workload identity findings
- Open Exposure > Security Posture.
- Select the Workload and agent identity category.
- Narrow by Severity, Check or Connector. The search box matches the affected identity.
- Select a row to open the finding's drawer.
Read the finding drawer
Each finding shows only the sections that apply to its check. The usual order:
| Section | What it shows |
|---|---|
| App owner | Who owns the app: Microsoft, Your organization, Another tenant you've connected, Third party or Unknown. For a third-party app, the Owner tenant ID. The Verified publisher name, or Not verified. Used by GraphnAI when the app is the one that applies GraphnAI's fixes. |
| Tenant-takeover permissions | Each permission and whether its path to Global Administrator is Direct or Through another object. |
| Credentials on this service principal | Each credential's name, type, when it was added and when it expires. Long-lived credentials add the limit and whether the credential is stored on the service principal or the app registration. |
| Admin roles held | Each Tier 0 role with its scope, the group it comes through, and Active or Eligible. |
| Other apps from this vendor in your tenant | The vendor's other apps, and whether each holds a tenant-takeover permission or a Tier 0 admin role. A stolen vendor credential can reach all of them. |
| Grants the app still holds | App role assignments, delegated grants and permission names for an app Microsoft disabled. |
| App consent | Whether consent is Everyone in your organization or a number of users, the sensitive permissions, and whether it Stays valid while signed out. |
| Who can add a credential | Each person or app that can add a secret to this app, and how: owns the service principal, owns the app registration, an admin role over this app, or a role over every app's credentials. |
| App registration owners | The owner count, and the disabled owners. |
| Why this app is privileged | The tenant-takeover permission, application permission or admin role that makes the app privileged. |
| Compared with similar apps | The deviation in standard deviations, the peer group and its size, and the permission weight. |
| Sign-in activity | The app's last sign-in. |
Below those, Why this matters, How to fix it and Frameworks follow. How to fix it can add one more line chosen from the evidence, for example:
- an app that applies GraphnAI's fixes, which needs its permission;
- the Microsoft Entra Connect app, with advice to protect the Entra Connect server and its certificate;
- a hybrid deployment's expected credential;
- a vendor app, with the disable-first advice below;
- an app in another tenant you've connected.
Frameworks shows MITRE ATT&CK technique IDs and OWASP Non-Human Identities Top 10 chips such as NHI5. Hover a chip for its title.
A service principal's node detail in the graph also shows Verified publisher, Disabled by Microsoft, Credentials (a count) and App owner organization.
Respond to a vendor app compromise
Use this when Credential added to a third-party app's service principal or App disabled by Microsoft still holds permissions fails on an app another organization owns.
- Open the finding and check App owner and Other apps from this vendor in your tenant.
- In Microsoft Entra, disable the service principal. Don't delete it: deleting removes consent, and the vendor's app would need to be consented again.
- Find out who added each credential and when. Remove the ones you didn't add.
- Remove permissions and admin roles you didn't grant, on this app and on the vendor's other apps.
- Contact the vendor and check its security advisories for the app.
Remove a tenant-takeover permission or an admin role
Two checks offer Select Fire:
- Service principal holds a tenant-takeover permission removes the app permission.
- App service principal holds a Tier 0 admin role removes the role assignment.
- Open the finding's drawer and select Select Fire.
- Review the access plan. It lists the permission or role the app would lose.
- Preview and simulate the change. The app loses the permission or role at once, and anything it does with it stops working.
- Approve the change. Both steps are manual only, so GraphnAI never runs them unattended and never preselects them.
See Select Fire. Check App owner first. If it says Used by GraphnAI, the app needs that permission to apply fixes.
Fix everything else in Microsoft Entra
The other checks have no automated fix. The finding names what to do, and you do it in Microsoft Entra:
| Check | Fix |
|---|---|
| Credentials on a Microsoft first-party service principal | Find who added the credential and when, then remove it. |
| Long-lived service principal credential | Add a credential that expires within 12 months (24 for a certificate), switch the app to it, then remove the old one. Remove secrets the app no longer uses. |
| Privileged service principal authenticates with a secret | Switch to a certificate or a federated credential, then remove the secret. |
| Illicit or over-consented OAuth grant | Review who consented and why. Revoke the consent in the enterprise application's permissions if no one can account for it. |
| Non-privileged owner of a privileged app or service principal | Remove owners who aren't Tier 0 administrators, or remove the permissions that make the app privileged. |
| Privileged app registration with no active owner | Give the app an owner who is accountable for it, or remove its permissions. |
| Service principal has more permissions than its peers | Review the permissions against similar apps with the app's owner, and remove the ones it doesn't need. |
| Dormant service principal is still privileged | Remove its permissions and credentials, or disable the service principal. |
| Service account can log on interactively | Limit the account to the computers it runs on with Log On To, or deny it interactive logon by Group Policy. |
Configuration
There's nothing to turn on. The checks run on every connected Entra ID tenant and every Active Directory domain with the bridge.
| Setting | Where | Effect |
|---|---|---|
| Entra ID sync | Admin > Identity Providers | Collects the data the Entra checks read. Sync now refreshes it. |
Troubleshooting
A check reads "Not assessed" and says "Collected at the next Entra sync"
The data was added in a newer release and hasn't been collected yet. Open Admin > Identity Providers, choose the tenant and select Sync now.
Service principal has more permissions than its peers reads "Not assessed"
Peer comparison hasn't run for the connector. It runs with the over-permission analysis after a sync. Open Over-Permissioned Identities to check that it has run.
Dormant service principal is still privileged reads "Not assessed"
The check needs service principal sign-in activity, which the sync doesn't collect. It never reads Passing without that data.
A check reads "Assessed N of M"
N is how many the check reached. Read the reason after the count. The remaining accounts are left out of the verdict until the reason is fixed. See Assessed N of M.
An app I expected to flag doesn't appear
Check its App owner. The credential checks split by owner: Microsoft apps, third-party apps and your own apps are different checks. Illicit or over-consented OAuth grant skips apps with a verified publisher, and Long-lived service principal credential skips apps another organization owns.
I removed a permission and the finding is still there
The finding stays until the next Entra sync confirms the change. It's marked "Fixed, confirming at next collection".
Related
In the catalog
- App disabled by Microsoft still holds permissions (T1199, T1550.001)
- Privileged app registration with no active owner
- Dormant service principal is still privileged (T1078.004)
- Credentials on a Microsoft first-party service principal (T1098.001)
- Service account can log on interactively (T1078.002)
- Illicit or over-consented OAuth grant (T1528)
- Non-privileged owner of a privileged app or service principal (T1098.001)
- Long-lived service principal credential (T1098.001)