HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Intune IntuneRBACScope TagsMicrosoft GraphPowerShellLeast Privilege

You Scoped That Admin to One Scope Tag. They Can Still See Every Untagged Object.

IA
Imran Awan
31 July 2026

You onboard a new regional helpdesk team. You build them a role assignment scoped to a single scope tag — call it Helpdesk-West — and everyone in the change ticket signs off happy: these admins can only see and touch West devices and West policies, nothing else. Six weeks later one of those helpdesk admins opens a compliance policy they should never have been able to see, edits the grace period on it, and quietly breaks Conditional Access for a site three time zones away. When you pull the audit log, the role assignment is exactly as scoped as it was on day one. Nobody changed the tag. So how did a West-scoped admin end up editing an object that belongs to nobody's region?

Because a scope tag is not a wall. It is an allow-list of what an admin can see, and Intune quietly fills the gap for everything you forgot to put on that list. This post walks through exactly why that happens, the one property that decides it, a manual check you can run against a single object before you trust anything, and a read-only PowerShell script that enumerates every configuration profile, compliance policy and app in your tenant and flags the ones that are silently visible to every scoped admin you have.

The problem — the portal shows a tidy boundary that does not actually exist

Open Tenant administration > Roles > All roles, pick the helpdesk role, and look at its assignment. You will see a clean, reassuring picture: Members = the West helpdesk group, Scope (Groups) = West devices, Scope (Tags) = Helpdesk-West. Every field says "West." The mental model that follows is almost irresistible: this admin lives inside a box called West and cannot see out of it.

That model is wrong in one specific, dangerous way. Scope tags decide which objects an admin can see, but they only ever add visibility — an object is visible to an admin if the object and the admin's role assignment share at least one scope tag. There is no such thing as "this object has no tag, therefore it is hidden from everyone." Microsoft's RBAC documentation is blunt about the edge of this behaviour:

Straight from Microsoft Learn: "If a role assignment has no scope tag, that IT admin can see all objects based on the IT admins permissions. Admins that have no scope tags essentially have all scope tags." A missing tag on the assignment is not a smaller box — it is no box at all.

The West assignment does have a tag, so it is not the no-tag case. But the same open-by-default logic reaches it from the other direction — through the objects. And that is the part almost nobody checks.

Why it happens — the Default scope tag is applied to everything you did not tag

Here is the mechanism, stated exactly. Intune ships one built-in scope tag called Default. Per the official RBAC and scope tags guidance, "The default scope tag is automatically added to all untagged objects that support scope tags." You do not opt in to this and there is no way to turn it off. Every configuration profile, compliance policy and app that nobody explicitly tagged carries the Default tag, whether you can see that in the blade or not.

Now pair that with how visibility resolves. Microsoft's Group Policy analytics guidance describes the untagged case from the object's point of view in a way that generalises to every object type: "If you don't select a scope tag, then the Default scope tag is automatically used. Only admins scoped to the Default scope tag can see the imported [object]. Admins that aren't scoped to the Default scope tag don't see the imported [object]."

Read that carefully, because the leak is hiding in the word "only." An untagged object is visible to every admin whose role assignment carries the Default tag. And the Default tag is the one almost every role assignment ends up carrying — either because it was left selected when the assignment was created, or because the assignment was given no tags at all (which, per the red callout above, is the same as having all of them). So the real boundary is not "West sees West." It is "West sees West plus every object in the entire tenant that nobody remembered to tag."

How an untagged compliance policy reaches a West-scoped admin
New compliance policy created — nobody sets a Scope (Tag)
Intune auto-applies the Default tag (id 0) — roleScopeTagIds = ["0"]
West helpdesk role assignment carries Helpdesk-West AND Default
Shared tag = Default → the West admin can see and (with write permissions) edit the policy

The built-in Default tag is the tag with id 0 in every tenant — it is the one scope tag flagged isBuiltIn: true when you list them through Graph. That id is what the script later in this post keys off, though it resolves the tag by its built-in flag at runtime rather than trusting a hard-coded number.

Terminology worth locking down: Roles decide what an admin can do (the permissions). Scope (Groups) decide which users and devices they can act on. Scope (Tags) decide which Intune objects — policies, profiles, apps — they can see. These are three independent axes. An admin can hold a read-only role, be scoped to a tiny device group, and still see thousands of untagged objects across the tenant, because object visibility rides entirely on the tag axis and nothing else.
⚠ Two gotchas that widen the gap: First, Intune RBAC and scope tags do not apply to Microsoft Entra roles — per Microsoft, "the Intune Service Admins role has full admin access to Intune no matter what scope tags they have." Someone with the Entra Intune Administrator role ignores this entire model. Second, a handful of object types cannot carry scope tags at all — Corp Device Identifiers, Windows Autopilot devices, device compliance locations and Jamf devices — so you cannot use tags to hide those even if you want to.

There is also a subtle read-only property that is easy to misread. On a configuration profile, supportsScopeTags being false means the object is a legacy policy that predates scope tags; Microsoft notes that in that state "entities will not be visible to scoped users." That is the opposite failure — a legacy object nobody can see — and it is worth distinguishing from the visibility leak this post is about, which is entirely about objects that carry the Default tag and therefore are visible.

How to verify — check one object by hand before you trust any script

Before you run anything at scale, prove the mechanism to yourself against a single object you already understand. Pick one configuration profile that you are certain nobody ever tagged. In the Intune admin center, open it and go to Properties > Scope (Tags). If the only entry is Default, that object is visible to every admin in your tenant whose role assignment includes the Default tag — which is almost all of them.

Intune admin center — Devices › Configuration › "Win11 - Baseline Firewall" › Properties › Scope (Tags)
Scope tags
Default ← the only tag on this profile
No custom scope tag is assigned. Every admin whose role assignment carries the Default tag can see this profile, regardless of which region or team they belong to.

If you would rather confirm it in code — which is the honest way to check, since the blade hides the underlying id — read the roleScopeTagIds property directly through Microsoft Graph. That property is documented on the configuration profile, compliance policy and app resources alike as the "List of Scope Tags for this Entity instance." An untagged object comes back with a single value: the Default tag's id, 0.

PowerShell 7 — manual spot-check on a single profile
# Least-privilege read scope for RBAC + config objects Connect-MgGraph -Scopes "DeviceManagementRBAC.Read.All","DeviceManagementConfiguration.Read.All" -NoWelcome # Which tag is the built-in Default? (it is id 0, isBuiltIn = true) Get-MgBetaDeviceManagementRoleScopeTag | Where-Object IsBuiltIn | Format-Table Id, DisplayName, IsBuiltIn Id DisplayName IsBuiltIn -- ----------- --------- 0 Default True # Read the scope tags actually on one profile (Get-MgBetaDeviceManagementDeviceConfiguration -DeviceConfigurationId "<id>").RoleScopeTagIds 0 # <-- only the Default tag. This profile leaks to every Default-scoped admin.
Gotcha: roleScopeTagIds is fully populated on the /beta endpoint and on the beta Graph PowerShell module (Microsoft.Graph.Beta.DeviceManagement.Administration). Some v1.0 list calls have historically returned the property empty or omitted it on certain object types, so the script below targets beta deliberately — and treats an empty roleScopeTagIds the same as "only Default," because an object that reports no tags at all is exactly as exposed.

The fix — enumerate every object and flag the ones scoped only to Default

You cannot fix what you cannot count, and clicking Properties on a few hundred profiles by hand is not an audit. Get-ScopeTagCoverageReport.ps1 connects with the least-privilege read scopes, resolves the built-in Default tag, then walks every configuration profile, compliance policy and app in the tenant and reports which ones carry only the Default tag or no tag at all — the objects that are silently visible to every scoped admin. It changes nothing.

✅ Read-only, by design: This script only performs GET requests against Microsoft Graph. It never creates, edits, assigns, removes or deletes a scope tag, a policy or a role assignment. It is safe to run against production in the middle of the day. Tagging the objects it finds is a deliberate, human decision you make afterwards — the script only surfaces the list.
Download the script — GitHub

Get-ScopeTagCoverageReport.ps1 is free and open source. Download it from the Imran76Awan/Daily-Tasks repository on GitHub — no sign-in required. It is read-only and cannot change anything in your tenant — but always validate any script in your own environment before you rely on it.

Get-ScopeTagCoverageReport.ps1 View full repo →

Connect it one of two ways. For an interactive run, -UseDeviceCode gives you a browser sign-in. For a scheduled, unattended run, pass app-only certificate auth with -TenantId, -ClientId and -CertificateThumbprint — the app registration needs only the three read scopes: DeviceManagementRBAC.Read.All to list the scope tags, DeviceManagementConfiguration.Read.All for configuration profiles and compliance policies, and DeviceManagementApps.Read.All for apps. Nothing writes, so no ReadWrite scope is ever requested.

Get-ScopeTagCoverageReport.ps1 — first run against a real tenant
Connecting to Microsoft Graph (device code)... Connected. Tenant: contoso.onmicrosoft.com Resolving built-in Default scope tag... Default scope tag id : 0 (DisplayName "Default", IsBuiltIn True) Custom scope tags : 6 (Helpdesk-West, Helpdesk-East, Kiosks, ...) Enumerating objects and reading roleScopeTagIds... Device configuration profiles : 214 Compliance policies : 38 Apps : 402 ---------------------------------------------- Objects scanned : 654 ================================================================ SCOPE TAG COVERAGE REPORT - 31 Jul 2026 09:41 ================================================================ Objects with a custom scope tag : 511 Objects visible to ALL scoped admins : 143 - only Default tag : 121 - no tag at all : 22 ---------------------------------------------------------------- Custom-tag coverage : 78.1% ================================================================ Objects scoped only to Default (leak to every Default-scoped admin): ObjectType DisplayName RoleScopeTagIds ---------- ----------- --------------- compliancePolicy Win11 - Baseline Firewall 0 compliancePolicy iOS - Corporate Passcode (none) deviceConfiguration Win11 - OneDrive KFM 0 deviceConfiguration MacOS - Wi-Fi Corp (none) mobileApp Company Portal (iOS) 0 mobileApp Contoso VPN (Win32) 0 ... (137 more) ... ACTION: assign a real scope tag to each object above, or confirm it is intended to be tenant-wide. Re-run to confirm the count drops. Exit code: 2

The core of the script is deliberately small. It resolves the Default tag once, builds a combined list of every object with its roleScopeTagIds, and flags anything whose tag set is empty or contains nothing but the Default id. Every Graph call is wrapped so that a failure sets an error flag and exits non-zero — it never prints "0 findings, all healthy" after a query that actually failed.

Get-ScopeTagCoverageReport.ps1 — the leak test
function Test-OnlyDefaultTag { param([string[]]$TagIds, [string]$DefaultId) # Empty tag set = as exposed as "only Default" if (-not $TagIds -or $TagIds.Count -eq 0) { return $true } # Leaks if EVERY tag on the object is the Default tag $nonDefault = $TagIds | Where-Object { $_ -ne $DefaultId } return ($nonDefault.Count -eq 0) }

Proof it worked — tag the leaks, then watch the coverage number climb

Work the list. For each flagged object, either assign the real scope tag it should have had all along (Properties > Scope (Tags) > Edit), or make a conscious decision that it genuinely is meant to be tenant-wide — a Company Portal app, say, that every admin legitimately needs to see. There is no auto-fix here on purpose: assigning the wrong tag can hide an object from the team that actually owns it, so every entry is a judgement call, not a bulk operation.

After a tagging pass, run the script again with -ExportCsv so you have a dated before/after artifact for the change record. The leak count falls to whatever you consciously chose to leave tenant-wide, and the custom-tag coverage climbs:

MetricFirst runAfter tagging pass
Objects scanned654654
Objects visible to all scoped admins14318
  — only Default tag1216
  — no tag at all220
Custom-tag coverage78.1%97.2%
Left tenant-wide on purpose (documented)18
Get-ScopeTagCoverageReport.ps1 -ExportCsv — re-run after remediation
SCOPE TAG COVERAGE REPORT - 31 Jul 2026 16:20 Objects with a custom scope tag : 636 Objects visible to ALL scoped admins : 18 (all reviewed and intended) ---------------------------------------------------------------- Custom-tag coverage : 97.2% CSV written: C:\Reports\ScopeTagCoverage_2026-07-31_1620.csv 18 tenant-wide objects remain, each confirmed intentional. Exit code: 2
Note on the exit codes: the script returns 0 when nothing leaks, 2 when it finds objects scoped only to Default, and 1 if any Graph query failed. That 2 on the "clean" re-run is expected — the 18 objects you deliberately left tenant-wide still count as findings. Reconcile the CSV against your documented allow-list rather than chasing the exit code to zero. And remember the harder limit: none of this touches anyone holding the Entra Intune Administrator role, who sees everything regardless. Scope tags are a distributed-IT convenience, not a security boundary against a privileged identity.
⚠ One more thing worth knowing: in March 2026 Intune introduced an opt-in public preview called Scoped permissions that changes how permissions merge when an admin holds multiple role assignments with different scope tags. It does not change the Default-tag visibility behaviour this post is about, but if you run distributed IT at any scale, read the Permissions Assessment Report before you enable it — the change cannot be reversed.
💼 Need this done for you?
Not sure what your "scoped" admins can actually see?

I'll run this coverage report against your tenant, walk you through every object that leaks past its intended scope, and help you design a scope-tag strategy that actually holds — without hiding objects from the teams that own them.

💬 See how I can help → 📅 Book a free call

References

Download this script free: Get-ScopeTagCoverageReport.ps1 is a read-only audit script — it never assigns, edits or removes a scope tag. Safe to run against production while you build up a picture of which objects fall outside your intended scope-tag coverage.
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Intune
Your Intune Filter Matches Zero Devices and the Portal Won't…
An include assignment filter with a subtly wrong rule can match zero devices, so a policy…
Intune
How to Look Up a Windows Autopilot Device by Serial Number Using…
The exact Graph PowerShell filter syntax to look up any Autopilot device by serial number…
Intune
Top 10 Intune PowerShell Commands Every Admin Should Know
These 10 Microsoft Graph PowerShell commands are the foundation every IT admin and EUC…