Guides / Guide

Prompt templates for a Conditional Access review that finds the policy nobody remembers writing

By Michael Shreeves · 16 June 2026 · M365 & Security · 6 min read

Background

Conditional Access policies accumulate. One gets written for a pilot group during a rollout and never gets cleaned up once the rollout finishes. Another gets added to fix one specific complaint from one specific user and ends up scoped far wider than the problem it solved. A year in, a tenant can easily have fifteen or twenty policies, several of which overlap, contradict, or exclude a group that no longer needs excluding - and nobody currently working there wrote most of them.

Reading a Conditional Access export and asking an AI tool to "review our Conditional Access policies" gets you a generic security lecture about zero trust. What actually finds the real problems is asking it to reason about the interactions between policies - which one silently defeats another, which exclusion group has grown to include people it was never meant to, and which policy hasn't been touched since a project that's long since finished.

Setup

The shape every template below follows:

  • Role - a security-minded reviewer reading real exported policy data, not a general security consultant giving generic advice.
  • Context - what's being handed over (an export of your actual policies) and what should come back (specific findings tied to specific policy names, not general best practice).
  • Inputs - the real policy names, conditions, and exclusion lists, either pasted or summarised.
  • Task - find contradictions, dead policies, and scope creep, not restate what Conditional Access is for.
  • Constraints - no invented policy names, and no recommendation to change a live policy without a stated review/test step first.

Conflict and redundancy check

For finding where two policies are actively working against each other, which is the most common way a Conditional Access setup quietly stops doing what everyone assumes it does:

You're reviewing an export of our Conditional Access policies for
conflicts and redundancy.

Context: I'll paste a list of our policies with their conditions,
grant/block controls, and assignments. Find where policies interact badly
- don't restate what Conditional Access is or give generic zero-trust
advice.

Inputs:
- Policies (name, state, conditions, grant controls, included/excluded
  groups): [PASTE OR SUMMARISE THE EXPORT]

Task: for each policy, check whether another policy's exclusion could
undermine what it's trying to enforce - for example a strict MFA policy
that a broad "pilot group" exclusion quietly opts most of the tenant out
of. Flag any two policies that appear to contradict each other's intent.
Flag any policy set to "Report-only" that's been in that state long enough
it's probably been forgotten rather than genuinely still being tested.

Constraints: reference specific policy names from what I gave you, never
invent one. If a policy's purpose is genuinely unclear from what's here,
say so rather than guessing at intent.

Stale exclusion group audit

For the specific, very common failure mode: an exclusion group created for a temporary reason that never got cleaned up, and has since grown:

You're auditing exclusion groups used across our Conditional Access
policies for scope creep.

Context: return which exclusion groups are used in the most policies, and
which look like they were meant to be temporary based on their naming or
description.

Inputs:
- Exclusion groups and which policies reference them: [LIST]
- Group names and descriptions, and creation dates if known: [LIST]
- Roughly how many members each has, and whether that's grown over time
  if you know: [DESCRIBE OR "UNKNOWN"]

Task: flag any exclusion group whose name suggests it was meant to be
temporary ("pilot", "test", "legacy migration", a project name) but is
still live and referenced. Flag any exclusion group used across more than
one unrelated policy, which usually means it's become a general "opt-out"
group rather than the specific-purpose one it started as.

Constraints: don't recommend removing any group's access outright - the
output is a list of exclusions to verify with whoever owns each group, not
an instruction to act unilaterally on a tenant-wide security control.

Policy coverage gap check

For the opposite problem - not too many overlapping policies, but a real gap nothing currently covers:

You're checking our Conditional Access policies for coverage gaps.

Context: return specific scenarios our current policy set doesn't
address, based on what's actually configured - not a generic checklist of
"things Conditional Access can do."

Inputs:
- Current policies and what they cover (user risk, sign-in risk, device
  compliance, location, app-specific controls): [LIST]
- Roles or apps you know are sensitive but aren't sure are covered:
  [LIST, OR "NOT SURE, THAT'S WHAT I WANT YOU TO CHECK"]
- Any known exceptions (break-glass accounts, service accounts, legacy
  apps that can't do modern auth): [LIST]

Task: cross-reference what's covered against common high-risk scenarios -
admin roles without a stricter policy than ordinary users, legacy
authentication left open for one app, no device-compliance requirement on
whichever apps handle sensitive data. Only flag a gap if it's actually
absent from what I've given you, not a hypothetical.

Constraints: distinguish clearly between "genuinely missing" and "covered
by a different mechanism you might not have mentioned" - ask rather than
assume if the export doesn't make it clear either way.

Edge Cases & BCP

  • Never paste real tenant data - user names, actual group membership, or anything identifying - into a public or consumer AI tool. Use policy names, conditions and role types with real identifying detail redacted, or a tool your organisation has actually approved for this kind of data, matching the same rule that applies to any tenant configuration data.
  • A model reviewing policy text has no way to confirm what's actually enforced in practice - a policy that looks correct on paper can still be undermined by something outside Conditional Access entirely (a legacy auth protocol still enabled at the tenant level, for instance). Treat every finding as a lead to verify in the actual admin centre, not a confirmed fact.
  • Break-glass/emergency-access accounts should show up as an intentional exception, not a finding to "fix". Make sure whatever you paste in identifies them as such, or the review will flag your own safety net as a security gap.
  • Any change this review suggests goes through a test/report-only pass before enforcement, the same as any other Conditional Access change - a policy correction applied directly to a live tenant on the strength of an AI-generated review, with no staged rollout, is exactly the kind of change that locks someone out at the worst possible time.
  • This finds configuration problems, not attacker behaviour. It won't tell you whether a policy has actually been bypassed or tested against real sign-in logs - for that you need your sign-in and audit logs, not a policy export.

← All guides