
A Full Access grant on a mailbox is the kind of audit event that makes you sit up. Someone, or something, has just been given the right to open a mailbox and read what is in it. In an MSP or SMB tenant that is not a change you ignore. It is also, as I was reminded this week, the kind of change Microsoft’s own Exchange service can generate as routine maintenance. The hard part is telling those two things apart quickly, without handing extra privilege to the tool that is helping you look.
My read-only Microsoft 365 monitoring bot flagged a burst of mailbox changes at 6:02–6:03pm the previous evening, including a Full Access grant. It did not assume the worst, and it did not start changing anything in the tenant. It asked me a straight question: was that burst me, or a Copilot or agent test?
I had not made any mailbox changes. I told it to investigate further. What follows is how that investigation ran, what the issue turned out to be, and how you can set up a similar read-only check of your own.
Why audit noise is hard to work with
The Microsoft Purview unified audit log is one of the most useful tools in a Microsoft 365 tenant. It is also one of the noisiest. A genuine mailbox permission change sits in the same log as scheduled Microsoft maintenance, directory sync, and admin work you already know about. The record is often technically correct and still hard to read at a glance.
That problem is sharper for MSPs and smaller IT teams. An MSP is watching this pattern across many tenants, usually without a 24-hour security operations centre. An SMB often has one or two people who also run the rest of the environment. In both cases the failure modes are the same. You either spend the evening chasing a change that Microsoft already documented as normal, or you scroll past something that deserved a closer look.
Alerts do not solve this by themselves. An alert can tell you that a Full Access grant happened. It cannot tell you whether the actor was a person, an app you own, or Exchange doing maintenance. It also cannot tell you, in plain English, what was touched and what was not.
I already use Grok Bot for a morning brief of MSP news and security updates. That is a different job. Industry news will not investigate a change inside your tenant. For that, you need a bot with read-only access, a habit of asking you first, and a willingness to stop when it cannot see enough.
How Grok Bot helps
The value is not that the bot is cleverer than the audit log. The log already has the events. The value is the way the work is done:
- It monitors in read-only mode, so a routine check cannot become a change in the tenant.
- It asks the human first when something looks unusual, instead of guessing or firing a ticket.
- It investigates on request, then reports findings in plain English.
- It states gaps honestly. If it cannot confirm a permission is still in place, it says so, rather than quietly requesting more access for itself.
- When more access is genuinely needed, the human grants it, after the bot has explained what it needs and what the trade-offs are.
- It can pause for a safety check, including whether you are looking at the right tenant.
That last point matters more than it sounds. A useful investigation bot is sceptical, not eager.
A real investigation
The bot’s first message was the right one. It had seen a burst of mailbox changes at 6:02–6:03pm, including a Full Access grant, and it wanted to know whether that was me or a test.

I replied that I had made no mailbox changes the previous day, and asked it to investigate further.
It stayed read-only. The actor was not a user, and it was not one of my apps. It was Exchange’s built-in service account, NT SERVICE\MSExchangeAdminApiNetCore, running from inside Microsoft’s own servers. It had only touched Exchange’s built-in system mailboxes. No user mailbox was changed, and no forwarding was set.
The Full Access grant was also narrower than it first appeared. It gave the built-in Discovery Management role group access to the Discovery Search mailbox. That is Exchange’s eDiscovery role group, and Microsoft documents this permission as the default. The same pattern had already run about 20 times between 12 October and the day of the alert. It only looked suspicious because the audit record showed the account’s identifier rather than its name.
That reading matches Microsoft’s own documentation. In the audit log activities guidance, Microsoft says you may see NT SERVICE\MSExchangeAdminApiNetCore on mailbox permission events, that this is a system account in the Exchange service in the Microsoft cloud, and that a common audited activity is updating permissions on the Discovery Search mailbox to verify that Full Access — “which is the default” — is assigned to Discovery Management. If you want to check that kind of claim while you investigate, the Microsoft Learn connector in Grok Bot is the straightforward way to pull the official wording rather than relying on memory.
So the story in the audit log was already pointing to routine maintenance. There was still a gap.
Closing the last gap
The bot was honest about what it could not do. It could see the audit events, but the read-only app could not read current Exchange mailbox permissions, so it could not confirm the Full Access grant was still in place. It did not request extra permission for itself, and it did not grant itself any.
Instead, it explained the access it needed, and I granted it. That was the Exchange.ManageAsApp application permission, with admin consent, plus the Global Reader role.
This is where least privilege deserves a proper look. Exchange.ManageAsApp lets an app connect to Exchange Online PowerShell without a user sign-in, but it is not a blank cheque. Microsoft still requires an Entra role or an Exchange role group to decide what the app is allowed to do. Global Reader is a supported choice for that, and Microsoft describes it as the read-only counterpart to Global Administrator: it can read settings and administrative information across Microsoft 365 services, but it cannot take management actions.
It is still broader than this particular check required. In Exchange Online, Global Reader maps to the View-Only Organization Management role group, whose members can view the properties of any object in the organisation. If all you need is Exchange visibility, adding the app to View-Only Organization Management is the narrower path. Global Reader also grants read access across other Microsoft 365 admin centres. The bot pointed that alternative out. I chose Global Reader anyway, because I wanted the broader read-only view for this monitoring bot and I was the person granting it. The trade-off was explicit. That is the standard I want: the human decides, with the narrower option on the table.
There was one more useful pause. I sent a screenshot from the admin portal so the bot could see the consent and role grant. The header showed a name that made it stop and warn me I might be in the wrong tenant. It was actually this tenant’s display name. I would rather a bot hesitate over a familiar name than charge ahead in the wrong directory.
With the access in place, the bot connected app-only to Exchange Online PowerShell, ran only Get-* read cmdlets, and disconnected. It confirmed that Discovery Management still has Full Access on the Discovery Search mailbox. The permission is not inherited, and it is not a deny entry. That matches Microsoft’s documented default, and it was still in place after the maintenance. Nothing in the tenant was changed. The evidence was written to an investigation file with no secrets in it.
The outcome was straightforward: routine Exchange Online maintenance, no incident. It was all resolved the next morning, within minutes of the access being granted.
Example prompts
These are the kinds of prompts I would start with if you want the same behaviour.
Set the bot’s role:
You are a read-only Microsoft 365 security monitoring bot for an MSP. Watch the unified audit log for unusual mailbox permission changes, forwarding, and similar high-impact events. When you see something that looks unusual, ask me whether it was expected before you investigate. Stay read-only. If you hit a permission gap, tell me what you cannot see and what access would close that gap. Do not request or grant yourself extra permission.
Create a recurring check:
Create a routine called Mailbox permission watch. Every weekday at 8:15am Sydney time, search the unified audit log for mailbox permission changes since the last run, including Full Access grants and forwarding changes. If nothing material happened, tell me that in this chat and stop. If something looks unusual, summarise it in plain English and ask me whether it was expected before investigating further. Stay read-only.
When an alert appears:
I made no mailbox changes yesterday. Please investigate further. Stay read-only. Identify the actor, what was changed, whether any user mailbox was touched, and whether forwarding was set. If the actor looks like a Microsoft system account, check the official Microsoft documentation and tell me if this is a known maintenance pattern. If you cannot confirm the current permissions, say so clearly and do not try to expand your own access.
After you have granted extra read access:
I have granted the access we discussed. Connect app-only to Exchange Online PowerShell, run only Get-* cmdlets, confirm whether the permission is still in place, then disconnect. Record the findings in an investigation file with no secrets. Change nothing in the tenant.
How to set up a similar read-only check
You can do most of this in chat. The only app locations I will point you to are ones I have verified: the per-agent info pane, and Settings for timezone.
1. Give a bot a clear role
Use a dedicated bot for tenant monitoring, so investigation work is not mixed with unrelated chats. Click the agent’s name in the chat header, or use Cmd+Shift+I, to open the per-agent info pane. The gear beside the X opens the per-agent settings for avatar, name, title and description. Give it a clear description: read-only monitoring, ask first, investigate on request, state gaps honestly, never escalate its own permissions.
2. Start with read-only audit access
Give that bot read-only access to the unified audit log through an app you control. Start with enough access to search the log, and nothing more. The investigation above got a long way on audit events alone.
3. Save the behaviour in chat
Use the role prompt above. Be explicit that the bot must ask you before digging in, must stay read-only, and must not request or grant itself extra permission.
4. Add Microsoft Learn for official checks
Add the Microsoft Learn connector if you want official documentation checked during an investigation, rather than after the fact. I walked through that setup in How to Set Up MCP Connectors in Grok Bot with Microsoft Learn.
5. Create a routine
Create the routine in chat. You can review saved routines in the same per-agent info pane, under the computer preview. Check the timezone under Settings, on the General tab, opened from the sidebar account button at the bottom-left, or with Cmd+,. Routines usually start within a few minutes either side of the time you set. If the run must start right on the minute, say “exactly” or “sharp”.
6. Grant extra access yourself when a gap appears
For a current mailbox permission check, that means Exchange.ManageAsApp with admin consent, plus a view-only role. Prefer View-Only Organization Management if you only need Exchange visibility. Use Global Reader only if you have a reason for the broader Microsoft 365 read access, and make that choice deliberately.
7. Keep an investigation trail
A file of findings with no secrets in it is more useful the next time the same maintenance burst appears.
What I took from it
The first lesson is the oldest one in this kind of work: verify before you panic. A Full Access grant is worth taking seriously. In this case it was Microsoft putting a documented default back where it already belonged. The audit log looked worrying because it showed an identifier instead of a familiar name. That is not a reason to ignore the alert. It is a reason to investigate it properly.
The second is least privilege. The bot did not help itself to more access when it ran out of visibility. I granted the extra permission, and I accepted a broader role than the narrowest option on the table. I am comfortable with that choice. I would not have been comfortable if the tool had made it for me.
The third is to keep the human in charge. The useful pattern was simple. The bot watched, asked, investigated, admitted a gap, explained the access it needed, paused when a screenshot might have been the wrong tenant, ran only read commands, and wrote down what it found. I still made the calls that mattered.
That is what simplified the security check. Not a dashboard, and not a promise that every alert is harmless. I went from a worrying Full Access grant to a documented, no-incident conclusion the next morning, without the tool quietly expanding its own reach. For an MSP, that is the difference between an audit event that ruins the start of the day and one that has already been explained.





