Existing check search
Provider
Microsoft 365
New provider name
No response
Service or product area
entra
Suggested check name
entra_app_registration_no_password_credentials
Context and goal
- Security condition to validate: No application registration in the tenant has any entry in
passwordCredentials (client secrets). Customer-owned applications should authenticate using certificates (keyCredentials), federated identity credentials (federatedIdentityCredentials), or managed identities — never long-lived shared secrets.
- Why it matters: Client secrets are bearer credentials that are easy to leak (committed to repos, copied into CI variables, shared via chat). Once leaked they can be used from anywhere on the internet until rotated. Microsoft's official guidance for the identity platform is to migrate away from client secrets in favour of certificate-based authentication, federated identity credentials, or managed identities. Prowler already has
entra_default_app_management_policy_enabled, which checks the policy that prevents new secrets from being added; this new check audits the current state and surfaces apps that already hold secrets (legacy or pre-policy).
- Resource involved: Microsoft Entra application registrations (
/applications) and their passwordCredentials collection.
Expected behavior
- Resource or scope to evaluate: All application objects in the tenant via
GET https://graph.microsoft.com/v1.0/applications?$select=id,displayName,appId,passwordCredentials. Iterate every application and inspect passwordCredentials.
- PASS when: every application's
passwordCredentials collection is empty.
- FAIL when: at least one application has one or more entries in
passwordCredentials. The finding should report appId, displayName, the count of password credentials, and (where present) keyId, displayName, startDateTime, and endDateTime of each — so operators can correlate to the specific secret entry to remove in the portal.
- MANUAL when: not applicable.
- Exclusions / edge cases:
- Both expired and active
passwordCredentials count toward FAIL — expired entries are credential clutter that should be cleaned up regardless. Operators who want to ignore expired-only entries can use Prowler's mutelist mechanism on a per-app basis.
- The check operates on
applications (app registrations), not on servicePrincipals (enterprise apps from other tenants). Microsoft first-party app secrets do not appear here because they are owned by Microsoft tenants.
References
Suggested severity
Medium
Additional implementation notes
- Existing patterns to follow:
entra_app_registration_no_unused_privileged_permissions already iterates application registrations in prowler/providers/m365/services/entra/. Reuse that pattern. Extend entra_service.py so the loaded Application model exposes password_credentials (a list of {key_id, display_name, start_date_time, end_date_time} records) using $select=passwordCredentials on the existing applications listing.
- Permissions / scopes: No additional permissions beyond Prowler's M365 baseline (
Directory.Read.All already grants read access to applications and their credential metadata).
- PowerShell is NOT needed; the check uses Microsoft Graph v1.0 only.
- Related check (do NOT duplicate, complementary):
entra_default_app_management_policy_enabled audits the tenant-wide policy that blocks new password credentials. This new check audits the actual state: apps that currently hold secrets, regardless of when they were added.
- Metadata: follow the M365 metadata schema used by sibling checks under
entra/.
Existing check search
Provider
Microsoft 365
New provider name
No response
Service or product area
entra
Suggested check name
entra_app_registration_no_password_credentialsContext and goal
passwordCredentials(client secrets). Customer-owned applications should authenticate using certificates (keyCredentials), federated identity credentials (federatedIdentityCredentials), or managed identities — never long-lived shared secrets.entra_default_app_management_policy_enabled, which checks the policy that prevents new secrets from being added; this new check audits the current state and surfaces apps that already hold secrets (legacy or pre-policy)./applications) and theirpasswordCredentialscollection.Expected behavior
GET https://graph.microsoft.com/v1.0/applications?$select=id,displayName,appId,passwordCredentials. Iterate every application and inspectpasswordCredentials.passwordCredentialscollection is empty.passwordCredentials. The finding should reportappId,displayName, the count of password credentials, and (where present)keyId,displayName,startDateTime, andendDateTimeof each — so operators can correlate to the specific secret entry to remove in the portal.passwordCredentialscount toward FAIL — expired entries are credential clutter that should be cleaned up regardless. Operators who want to ignore expired-only entries can use Prowler's mutelist mechanism on a per-app basis.applications(app registrations), not onservicePrincipals(enterprise apps from other tenants). Microsoft first-party app secrets do not appear here because they are owned by Microsoft tenants.References
applicationresource: https://learn.microsoft.com/en-us/graph/api/resources/application?view=graph-rest-1.0passwordCredentialtype: https://learn.microsoft.com/en-us/graph/api/resources/passwordcredential?view=graph-rest-1.0Suggested severity
Medium
Additional implementation notes
entra_app_registration_no_unused_privileged_permissionsalready iterates application registrations inprowler/providers/m365/services/entra/. Reuse that pattern. Extendentra_service.pyso the loadedApplicationmodel exposespassword_credentials(a list of{key_id, display_name, start_date_time, end_date_time}records) using$select=passwordCredentialson the existing applications listing.Directory.Read.Allalready grants read access to applications and their credential metadata).entra_default_app_management_policy_enabledaudits the tenant-wide policy that blocks new password credentials. This new check audits the actual state: apps that currently hold secrets, regardless of when they were added.entra/.