Skip to main content
Conditional AccessEntra IDIntuneDevice ComplianceMFA

Your Conditional Access Device Filters Are a Paper Wall

Rawson Wade13 min read
Your Conditional Access Device Filters Are a Paper Wall

We keep seeing a recurring pattern in our engagements. An organisation has configured device filters in Conditional Access as a security control to help with end user experience. They've picked their platforms, blocked non-compliant devices, and ticked the boxes. Then we review their policies using SuiteAuth Toolkit and expose significant gaps in their MFA policies caused by an over-trust in the device identity and a lack of a baseline MFA policy.

No exploits. No zero-days. Just a user agent string and an understanding of how Entra ID evaluates what device you're using.

This post covers the three bypass patterns we run into most often, and what to do about them. If you only remember one thing from this article: a baseline MFA policy with limited exclusions is the single most important control you have in your tenant, and no amount of device filtering makes up for not having one.

How does Entra ID actually know what device you're using?

Most admins we talk to assume there's some kind of deep inspection going on behind the scenes to determine the device a user is using. Unfortunately, that isn't the case.

When you set a Device Platform condition, Entra ID has two options to determine the platform. First it uses the Operating System if a device signal is present (e.g. from a PRT). Otherwise it falls back to reading the User Agent string from your browser. Your browser tells Entra "I'm Windows" and Entra believes it. The problem: both the User Agent string and the Device Operating System are self-reported.

If you implement a more in-depth Device Filter, Entra queries the device object registered in the directory and checks its attributes. If the device isn't registered at all, every attribute comes back as null.

These two mechanisms are completely independent. The gap between them is where all three bypasses live.

Device Platform condition → Read from Registered Device [when present] (self-reported, unverified)
Device Platform condition → Parsed from User Agent string (self-reported, unverified)
Device Filter condition   → Checked against registered device objects in Entra ID
Unregistered device       → All device properties = null

Here's how the platform detection actually works:

If an attacker sends a User Agent that doesn't match any platform you've written a policy for, no policy applies. They're in. If they register a device in an OS you aren't targeting, they're in. In both cases, Microsoft is making a best-effort guess on what platform the user is using.


Bypass #1 — Spoofing the User Agent

This is the easy one, and we demo it on almost every Microsoft Entra ID Conditional Access Review engagement.

What the client had: A Conditional Access policy requiring device compliance for Windows and macOS devices hitting M365.

What we did: Opened SuiteAuth, set up an Interactive OAuth, changed the User Agent to a Linux string, and watched the simulation run. Entra ID saw a Linux device. There was no policy covering Linux. We were in.

Ten seconds of work. The sign-in logs dutifully recorded "Linux" as the platform, and unless someone was watching for that, nobody noticed.

Microsoft's own docs say it plainly:

Conditional Access identifies the device platform using information provided by the device, such as user agent strings. Because user agent strings can be modified, this information isn't verified.

Microsoft Learn: Conditions in Conditional Access policy

And on their page about blocking unsupported platforms, they repeat the warning:

The device platform condition is based on user agent strings. Conditional Access policies using this condition should be used with another policy, like one requiring device compliance or app protection policies, to mitigate the risk of user agent spoofing.

Microsoft Learn: Block unsupported platforms

The platform condition is a hint. It was never meant to be a security boundary. Treating it like one is the mistake.


Bypass #2 — The null problem with unregistered devices

This one is sneakier, and it catches admins who think they've written solid filter rules.

The setup: An admin writes a device filter to block anything where device.operatingSystem doesn't equal "Windows". Sounds reasonable. Only let Windows devices through.

The problem: A personal laptop that's never been registered in Entra ID has no device object. All its properties are null. And null doesn't equal "Windows", so the filter matches and... does what, exactly? That depends on how the policy was built, and this is where people get tripped up.

Microsoft spells this out in their device filter docs:

For a device that is unregistered with Microsoft Entra ID, all device properties are considered as null values and the device attributes cannot be determined since the device does not exist in the directory.

Microsoft Learn: Filter for devices

And their recommended workaround:

The best way to target policies for unregistered devices is by using the negative operator since the configured filter rule would apply.

— Same page

Here's the practical difference:

What you wantHow you configure itRegistered non-Windows deviceUnregistered device
Block non-WindowsInclude where OS ≠ Windows✅ Blocked⚠️ Slips through
Block non-WindowsExclude where OS = Windows✅ Blocked✅ Blocked

The second version works because the exclusion only fires for devices that positively match "Windows". Everything else — including devices with null properties — stays in scope and gets blocked.

This is sometimes called the "double negative" pattern. It feels backwards when you're writing it, but it's the only way to catch unregistered devices:

  • Want to block something? Use: Exclude + positive operator
  • Want to allow something? Use: Include + negative operator

If you use a positive operator in an "Include" configuration for a blocking policy, unregistered devices will always slip through. Every time.


Bypass #3 — The bait and switch

This one combines both previous weaknesses. It's one of the more interesting pattern we run during assessments, and it's the reason we built our simulation tooling in the first place.

What the client had: Only Windows with Intune Compliance can access Microsoft 365 off the trusted network. Registering a Windows, iOS, or Android device requires Phishing Resistant MFA.

What we did:

The problem? They didn't require MFA for All Platforms to register a device. Leading to some sneaky MFA bypasses.

We ran a demo which lets us spoof any User Agent to Entra ID and register arbitrary device configurations to Intune.

SuiteAuth device registration setup showing a simulated Windows managed device being configured with identity, device type, and operating system fields, alongside a browser simulation set to a Linux User Agent — demonstrating how the tool prepares both the spoofed platform and the device registration in a single interface

First, we get an access token using a platform type nobody wrote a policy for (Linux). We use that token to register a Windows device. MFA would normally be required, but by using the bait-and-switch we are never prompted for it.

We can see that the spoofed User Agent is displayed in the Entra sign-in logs, the device is not compliant, and not managed:

Entra ID sign-in log Activity Details showing the Device info tab for a spoofed sign-in — Operating System is reported as Linux, Compliant is No, Managed is No, and both Device ID and Browser fields are blank, confirming the platform was accepted at face value with no Conditional Access policy applied

Then, from that initial authentication, we register a spoofed Windows device and enrol it in Intune for compliance. The SuiteAuth timeline on the right shows each step of the chain: authentication challenge, token exchange, device registration with Entra ID, primary refresh token acquisition, Intune enrolment, and finally the compliance check-in completing successfully:

SuiteAuth device registration result screen showing a successfully registered and Intune-compliant device named Demo Bait and Switch — the left panel displays the internal device ID, Azure AD device ID, registration metadata including join type and compliance status, along with access tokens, refresh tokens, and PRT details, while the right panel timeline traces the full attack chain from authentication challenge through token exchange, Entra ID registration, Intune enrolment, and compliance check-in

The gap between "what platform does the browser say it is" and "what device is actually registered in the directory" is a real architectural seam. These are two different trust signals and Entra evaluates them independently.

After a few moments of waiting (Intune can be a little slow to reflect the check-in) we can now start downloading all that user's data. Let's check their emails, files and chats:

SuiteAuth post-exploit screen showing a compromised user's Microsoft 365 mailbox accessed using the acquired tokens — the Emails tab is active displaying inbox messages including a test email titled Hello world, with options to browse Teams chats, OneDrive files, SharePoint sites, and directory data, demonstrating full data exfiltration capability after bypassing Conditional Access controls

Catching the bait and switch in your logs

So you've read this far and you're wondering: would I even notice if someone did this in my tenant? Probably not, unless you're specifically looking for it. But the telemetry is there. It is up to you to stitch it together.

The bait and switch leaves a distinctive trail across two separate log sources: SigninLogs and AuditLogs. The problem is that most SOC teams look at these independently. When you correlate them, the pattern stands out.

Here's what the attack looks like from a log perspective:

What to hunt for

The smoking gun is a platform change + new device registration from the same user in a short window. A user who signs in on Linux (or an unknown platform) with no CA policy applied, and then shortly afterwards registers a brand new Windows device that gets marked compliant. That doesn't look like the average Tuesday onboarding.

Here's a KQL query to scratch the surface of this pattern. It looks for users who had a sign-in followed by a device registration event from the same user within 1 hour which doesn't have a matching operating system (it's not perfect):

// Step 1: Sign-ins
let Signins = SigninLogs
| where TimeGenerated > ago(30d)
| where ResultType == 0
| project
    SigninTime = TimeGenerated,
    UserId = UserPrincipalName,
    SigninPlatform = tostring(DeviceDetail.operatingSystem),
    SigninIP = IPAddress;
// Step 2: Device registrations
let DeviceRegistrations = AuditLogs
| where TimeGenerated > ago(30d)
| where OperationName == "Register device"
| extend TargetUser = tostring(InitiatedBy.user.userPrincipalName)
| extend RegPlatform = tostring(AdditionalDetails[3].value) // OS reported during registration
| project
    RegTime = TimeGenerated,
    UserId = TargetUser,
    RegPlatform,
    DeviceName = tostring(TargetResources[0].displayName),
    RegIP = tostring(InitiatedBy.user.ipAddress);
// Step 3: Join and flag platform mismatches
Signins
| join kind=inner DeviceRegistrations on UserId
| where RegTime between (SigninTime .. (SigninTime + 1h))
| where  not(SigninPlatform startswith RegPlatform)
| project
    SigninTime,
    RegTime,
    TimeDelta = RegTime - SigninTime,
    UserId,
    SigninPlatform,
    RegPlatform,
    DeviceName,
    SigninIP,
    RegIP
| sort by TimeDelta asc

If this returns results, pay attention to a few things:

  • IP mismatch between the sign-in and the registration. If someone signs in from one IP on Linux and registers a device from a different IP shortly after, that's suspicious. In a legitimate scenario (someone setting up a new work laptop), these would normally be the same IP.
  • The time gap. A genuine user getting a new device might register it the same day they sign in. But if the gap is very short — minutes rather than hours — and the platform changed, that looks more like an automated attack chain than someone unboxing a new Surface.
  • Device names that look generic or auto-generated. Tools like ROADtools and similar leave telltale signs in the device object. Look at the device name, OS version strings, and user agent in the audit logs. A ROADtools registration will often show Microsoft.OData.Client as the user agent.

So how do you build policies that actually hold up?

We've broken three things. The answer is a pyramid of controls with a foundational baseline MFA policy at the base. Then you build mitigating controls on top.

Layer 4: Privileged access lockdownAdmin from known PAW by whitelisted devicesLayer 3: Device complianceAll users, all apps — require Intune-compliant deviceEXCLUDE + positive operator (double-negative pattern)Layer 2: Platform catch-allAll users, all apps, block when platform is not:Windows, macOS, iOS, Android, or LinuxLayer 1: Foundational MFA baselineAll users, all apps, zero conditions and limited exclusionsNo platform filter | no location exclusion | no compliance carve-outStops: credential theft, password spray, brute force, phished passwords

Each layer catches what the one below it misses. MFA is the wide base — it applies to everyone and stops the most common attacks. The platform catch-all narrows things further. Device compliance filters out anything unmanaged. And at the top, the tightest control: admin accounts pinned to specific physical machines.

Start with MFA. Apply it unconditionally.

This is the one we argue about with clients the most, and the one we're most insistent on.

Your MFA policy should have no conditions attached to it. None. No platform filters, no trusted location exclusions, no "skip if device is compliant" carve-outs.

Every condition you attach to an MFA policy is something an attacker can spoof. Exclude a trusted location? VPN. Exclude a platform? User Agent string. Exclude compliant devices? Register one.

What it should look like:

  Users:        All users (break-glass accounts excluded)
  Cloud apps:   All cloud apps
  Conditions:   None
  Grant:        Require MFA (phishing-resistant if possible)
What we usually find:

  Users:        All users
  Cloud apps:   All cloud apps
  Conditions:   Exclude trusted locations, exclude compliant devices
  Grant:        Require MFA
                ↑ each of these exclusions is a way in

On every engagement where we've bypassed device controls, an unconditional MFA policy would have stopped us or at least made our lives significantly harder. You can fake device compliance. You can spoof Global Secure Access for trusted location. You can change a User Agent string in seconds. Getting past a phishing-resistant MFA challenge tied to the actual human? That's a different proposition entirely.

Block unknown platforms

Don't just write policies for the platforms you know about. Write one that blocks everything you don't.

Lots of tenants still have a gap for Linux. Microsoft added it as a selectable platform a while back, but if your policies predate that, you might not have it covered. Check.

And remember: even a comprehensive platform block is only as strong as the User Agent string, so it needs to work alongside compliance requirements, not instead of them.

Use the double-negative pattern for device filters

When you want to block non-compliant or unregistered devices, configure the policy to Exclude matched devices using a positive operator. Everything that doesn't positively match — including devices with null properties — stays in scope.

If you use positive operators in an Include configuration for blocking, unregistered devices walk right through. We've covered why above, but it bears repeating because we see this misconfiguration constantly.

Layer compliance on top of platform controls

Platform = self-reported, spoofable. Compliance = checked against the directory, harder to fake (though not impossible, as we showed with the bait and switch).

Use both together. But make sure your compliance policies actually check something meaningful. A policy that only verifies "device is enrolled" isn't really verifying much.

Watch the logs

Even with solid policies, keep an eye on sign-in logs for things that look off: a user who's always on Windows suddenly showing up as Linux, a burst of new device registrations from unexpected sources, compliance state flipping on recently-registered devices, or sign-ins from unregistered devices to anything sensitive.


Are your policies actually doing what you think?

Quick gut-check:

  • Do you have an MFA policy with genuinely zero conditions on all users?
  • Is there a catch-all block for unknown or unsupported platforms?
  • Are your device filter rules using the double-negative pattern?
  • Do your compliance policies check actual device posture, not just enrolment?
  • Are admin accounts restricted to specific known device IDs?
  • Is anyone looking at sign-in logs for platform anomalies?
  • Is Device Code flow blocked for device registration and Authentication Method registration?

If any of those are a "no" or an "I'm not sure," your Entra ID Conditional Access Policies might not be doing what you think they're doing.

... Mandatory plug ...

When we run these assessments, we use our Entra ID authentication toolkit that lets us present arbitrary device configurations to Entra ID; spoofing platforms, registering devices, spoofing Microsoft App protection (MAM) and manipulating compliance state. All to prove the gaps your policies hold. If you want to pressure-test your Conditional Access setup, get in touch with us.

Rawson Wade

Written by

Rawson Wade

Labs Lead, Modern 42

Rory leads Modern 42's Labs team with deep expertise in Microsoft Entra ID and Azure identity platforms. He has delivered countless IAM and PAM implementations for Australian government and largest enterprise.

© Posts are provided 'as is' under the AGPL 3.0 license unless otherwise stated

conditional access device filters entra id user agent spoofing device compliance MFA identity security cloud security intune conditional access bypass

We use cookies

We use cookies and similar technologies to help personalise content, measure the performance of our site, and provide a better experience. By clicking Accept, you consent to the use of all cookies.
Learn more.