Existing check search
Provider
Microsoft 365
New provider name
No response
Service or product area
entra
Suggested check name
entra_conditional_access_policy_explicitly_targets_azure_devops
Context and goal
- Security condition to validate: At least one enabled Conditional Access policy explicitly includes the Azure DevOps cloud application (
appId 499b84ac-1321-427f-aa17-267ca6975798) in conditions.applications.includeApplications. The catch-all value "All" does not count as explicit targeting for this check.
- Why it matters: Azure DevOps is a high-value sign-in surface (source code, build pipelines, secrets, service connections to production). Operators frequently rely on a single "All cloud apps" Conditional Access policy and assume it covers Azure DevOps; in practice many organisations want a tighter, dedicated policy for Azure DevOps (different MFA prompts, device-compliance requirements, location restrictions, or session controls) because Azure DevOps clients — including the CLI, IDE plug-ins and PAT-based tooling — behave differently from a typical browser sign-in. This check enforces that an explicit Azure DevOps Conditional Access policy exists, so operators surface the decision and don't rely on the "All cloud apps" sweep alone.
- Resource involved: Microsoft Entra Conditional Access policies and their
conditions.applications.includeApplications collection.
Expected behavior
- Resource or scope to evaluate: All Conditional Access policies whose
state is enabled. For each, inspect conditions.applications.includeApplications.
- PASS when: at least one enabled policy lists the Azure DevOps
appId 499b84ac-1321-427f-aa17-267ca6975798 in includeApplications.
- FAIL when: no enabled policy lists that
appId explicitly. A policy whose includeApplications only contains "All" does not satisfy this check, by design — the goal is to verify a deliberate, dedicated decision was taken about Azure DevOps.
- MANUAL when: not applicable.
- Exclusions / edge cases:
- Report-only policies are out of scope:
state = enabledForReportingButNotEnforced policies do not enforce anything and should not be counted as protection.
- The check makes no claim about what the matching policy enforces (block vs require MFA vs require compliant device); it only verifies an explicit-targeting policy exists. Whether the policy is itself secure is the responsibility of other Conditional Access checks already in Prowler.
References
Suggested severity
Medium
Additional implementation notes
- Existing patterns to follow: Reuse the Conditional Access iteration pattern from
entra_conditional_access_policy_mfa_enforced_for_guest_users and entra_conditional_access_policy_directory_sync_account_excluded (prowler/providers/m365/services/entra/). The existing ConditionalAccessPolicy model already exposes state, conditions.applications.includeApplications, and conditions.applications.excludeApplications — no service change required.
- Permissions / scopes: No additional permissions beyond Prowler's M365 baseline (
Policy.Read.All already grants reads against Conditional Access policies).
- PowerShell is NOT needed; this check uses the Microsoft Graph data already loaded by the entra service.
- App ID constant:
499b84ac-1321-427f-aa17-267ca6975798 is Microsoft's stable, tenant-independent service principal appId for Azure DevOps Services (documented in the first-party Microsoft applications list referenced above). Hard-code it as a module-level constant in the check.
- 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_conditional_access_policy_explicitly_targets_azure_devopsContext and goal
appId 499b84ac-1321-427f-aa17-267ca6975798) inconditions.applications.includeApplications. The catch-all value"All"does not count as explicit targeting for this check.conditions.applications.includeApplicationscollection.Expected behavior
stateisenabled. For each, inspectconditions.applications.includeApplications.appId 499b84ac-1321-427f-aa17-267ca6975798inincludeApplications.appIdexplicitly. A policy whoseincludeApplicationsonly contains"All"does not satisfy this check, by design — the goal is to verify a deliberate, dedicated decision was taken about Azure DevOps.state = enabledForReportingButNotEnforcedpolicies do not enforce anything and should not be counted as protection.References
conditionalAccessApplications(includeApplications/excludeApplications): https://learn.microsoft.com/en-us/graph/api/resources/conditionalaccessapplications?view=graph-rest-1.0appIdlisted): https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-inSuggested severity
Medium
Additional implementation notes
entra_conditional_access_policy_mfa_enforced_for_guest_usersandentra_conditional_access_policy_directory_sync_account_excluded(prowler/providers/m365/services/entra/). The existingConditionalAccessPolicymodel already exposesstate,conditions.applications.includeApplications, andconditions.applications.excludeApplications— no service change required.Policy.Read.Allalready grants reads against Conditional Access policies).499b84ac-1321-427f-aa17-267ca6975798is Microsoft's stable, tenant-independent service principalappIdfor Azure DevOps Services (documented in the first-party Microsoft applications list referenced above). Hard-code it as a module-level constant in the check.entra/.