High-risk Microsoft Graph Permissions: Inventory and Controls
Series: five permissions that carry most application-level risk in an M365 tenant, and the declarative rules that bound them.
Why these five, and not the others
The Microsoft Graph permissions catalog has over 200 entries, with roughly a hundred in application flavor (read and write with no signed-in user). Most are narrow: DeviceManagementServiceConfig.Read.All, Reports.Read.All, Calendars.Read. Their compromise is annoying, rarely catastrophic.
Five stand apart. They share three properties:
- They are tenant-wide. No default scope, no native subset.
- They are requested by legitimate applications. Blanket-refusing breaks integrations nobody wants to lose.
- Their compromise translates to measurable harm: exfiltrated customer data, fraudulent wire transfers, reputational incidents, notification obligations.
This series breaks each permission into an incident scenario, the reason Microsoft does not block it natively, and a set of declarative rules to bound it. The same template applies to all five because the problem is structurally the same, and the solution, architecturally the same.
The inventory
Mail.Send
Unscoped send from any mailbox
A compromised app sends 12,000 phishing emails in 20 minutes from a legitimate mailbox. ApplicationAccessPolicy scopes sources, nothing controls recipients, content, or volume.
Typical harm: Direct damage to client trust, privacy breach notification, regulatory investigation.
Full case study and declarative rules →
Files.ReadWrite.All
Silent SharePoint exfiltration
Read access to every library on every site in the tenant. Sensitivity Labels and Purview DLP detect after the fact. No native equivalent to Sites.Selected.
Typical harm: Mass exfiltration (gigabytes per hour) below the radar of native detection.
Full case study and declarative rules →
Sites.FullControl.All
Internal pivot via access plan mutation
Complete control over every site. Can add guests, modify permissions, erase audit columns. The risk is not exfiltration, it is pivot.
Typical harm: Silent reconfiguration of the SharePoint access plan, discovered after a leak.
Full case study and declarative rules →
Application.ReadWrite.All
The permission that grants every other
Register new apps and grant any Graph permission, with no human in the loop. It is the root of nearly every tenant-wide escalation.
Typical harm: Total tenant compromise from a single leaked application secret.
Full case study and declarative rules →
User.Read.All
Silent reconnaissance before a targeted attack
Read access to the whole directory with titles, managers, departments. Invisible in native audit. Arms BEC and spear-phishing campaigns against the finance chain.
Typical harm: Targeted financial fraud, hijacked wire transfer, calibrated on exact hierarchical data.
Full case study and declarative rules →Limits shared by all five
The five controls rely on the same architecture. Naming the limits once avoids repeating them in every article.
- The proxy must be on the path. An application that keeps direct Graph credentials bypasses the layer. The correct trust model keeps the real Graph secret out of the application and issues it a proxy credential, useless anywhere else.
- Latency adds 20 to 50 ms per call. Invisible in transactional workloads, worth discussing for bulk, rarely an issue on real business volumes.
- Rules require an inventory. Which sites, which attributes, which legitimate apps. That work is not a byproduct of deployment, it is often the first operational benefit.
The posture shift
Without a governance layer, these five permissions form the surface where a leaked application secret quickly becomes a measurable incident. With one, every Graph call is evaluated before reaching Microsoft, and the blast radius of a leaked secret is reduced to the functional minimum.
The difference is not in detection (native tools and Purview already do plenty). It is in synchronous prevention: a refused call does not go out. Once that principle is in place, the operational question becomes: which rules, for which applications, in what priority order.
That is exactly why GraphWarden exists.