Group Membership Drift: Why Access Reviews Keep Failing
SyncMyGroup team · October 16, 2026
Every quarter, someone exports group memberships from a dozen tools into a spreadsheet, sends tabs to managers, and asks them to confirm who should still have access. The managers approve most of it, flag a few people who left months ago, and IT removes them. The review closes.
Next quarter, the same kinds of findings come back. Different names, same pattern: people who left, people who moved teams, contractors whose engagement ended, an alumni account in a private channel.
That isn't a failure of diligence. It's a structural problem. Group membership drifts every day, and a review is a snapshot. This post covers where drift comes from, why reviews alone can't fix it, and what to change so the review becomes a confirmation rather than a cleanup.
What drift is
Drift is the gap between who should be in a group and who actually is.
It's rarely one big event. It's an accumulation of small, reasonable actions that nobody reverses:
- A manager adds someone to
@platformin Slack "for now" while they help with a migration. - An engineer moves from Payments to Growth. They're added to the new Linear team and GitHub team, but nobody removes them from the old ones.
- A contractor's engagement ends. Their Google account is suspended, but they're still listed in a Jira group because that group was maintained by hand.
- Someone creates
#incident-payments-2as a private channel during an outage and invites twenty people. It never gets cleaned up. - An offboarding checklist covers Google, Slack and GitHub. It doesn't cover the PagerDuty team or the Zoom group.
Each one is small. Across a few hundred people and ten tools, they add up to a review that always finds something.
Why access reviews keep failing
Reviews are snapshots; drift is continuous
A quarterly review catches drift that exists on the day of the export. Everything that drifts the day after waits three months. If removals happen only during reviews, the average exposure for a stale membership is half the review interval, and every review starts from scratch.
Reviewers can't see what a group means
A spreadsheet row that says "eng-core (GitHub team), 47 members" tells a manager almost nothing. Which repositories does it grant? Is it the same as engineering@? Was it supposed to include contractors? Without context, reviewers approve what looks familiar. This is the rubber-stamp problem, and it isn't laziness. The reviewer genuinely can't tell.
The same group exists ten times
engineering@ in Google, @engineering in Slack, engineering in GitHub, Engineering in Jira, the Engineering PagerDuty team. Five lists of what's meant to be the same people, reviewed five times, by possibly five different owners. Each one drifts independently, so fixing one doesn't fix the others.
Nested groups hide members
If engineering@ contains platform@ and contractors-eng@, the export of engineering@ may show two group addresses rather than the people in them. Reviewers approve two lines; the actual access belongs to sixty people.
Removals lag the decision
Even when a reviewer flags someone, the removal is a ticket. If it's done by hand across several tools, it's easy to miss one. The next review finds the same person in the one tool that was skipped.
What the frameworks actually ask for
Access reviews exist because frameworks require you to control access rights through their whole lifecycle.
ISO/IEC 27001:2022, Annex A 5.18 (Access rights) covers provisioning, review, modification and removal of access rights. It replaced three 2013 controls (9.2.2, 9.2.5 and 9.2.6). The review frequency isn't fixed by the standard; you define it in your own policy and then have to follow it.
SOC 2's logical access criteria split the same lifecycle: CC6.2 covers registering and authorising users before access is granted, and CC6.3 covers modifying and removing access as roles change. Because SOC 2 Type II is tested over a period, auditors look at whether removals actually happened in time, not just whether a review meeting took place.
Neither framework requires you to find drift once a quarter. They require access to be correct. A periodic review is evidence that you checked. If access is correct between reviews, the review is short.
Fix drift at the source, then review less
The goal is to make drift hard to create and quick to undo, so the review is a confirmation.
1. Give every group exactly one source of truth
For each logical group, decide which system is authoritative. Usually that's a directory group: a Google Group, or an Entra ID group. Sometimes it's a team-owned list, like a Linear team or a PagerDuty schedule. Write it down.
Everything else becomes a derived group. Nobody edits derived groups by hand. If someone needs access, they're added to the source.
See one-way vs two-way group sync for how to choose.
2. Sync derived groups continuously
Derived groups should be rebuilt from the source automatically. When someone is removed from engineering@, they come out of @engineering, #engineering, the GitHub team, the Jira group and the PagerDuty team without a ticket.
This is the step that changes the review. If every derived group is kept in line with its source, you review the source groups only — one list per logical group, instead of ten.
3. Make exceptions explicit
Real groups always have exceptions: the deploy bot, the CTO who wants to be in #incidents, the auditor with read-only access for a quarter. If exceptions live as manual edits, they're indistinguishable from drift.
Keep them as a named list on each derived group. Then the review question is simple: "here are the three exceptions on this group; are they still needed?"
4. Log every change
Every add and remove should land somewhere a human can see it: an ops channel or an audit log. That gives you evidence for the auditor and an early warning when a mapping is wrong. It also catches the silent failure where a sync stops running and nobody notices.
5. Review the sources, the exceptions and the log
With the above in place, the quarterly review shrinks to three questions:
- Are the source groups correct? (One list per logical group.)
- Are the exceptions still justified?
- Did the sync log show anything unexpected?
Measuring your current drift
Before changing anything, measure how bad it is for one group. A quick comparison of a Google Group and a Slack user group:
# Google: direct + indirect members of the source group
src = {m["email"].lower()
for m in list_members(directory, "engineering@company.com",
include_derived=True)
if m["type"] == "USER"}
# Slack: members of the derived user group, resolved to emails
ids = slack.usergroups_users_list(usergroup="S0ENGINEER")["users"]
dst = {slack.users_info(user=u)["user"]["profile"]["email"].lower()
for u in ids}
print("In Slack, not in Google:", sorted(dst - src))
print("In Google, not in Slack:", sorted(src - dst))
The first list is your access risk: people with access the source doesn't grant. The second is your productivity cost: people who should be reachable and aren't. Run it for a few groups and you'll know whether the problem is a handful of people or a structural gap.
Where SyncMyGroup fits
SyncMyGroup does steps 2 to 4 for the tools it connects: Google Groups, Microsoft Entra ID, Slack user groups and channels, GitHub teams, GitLab groups, Jira / Atlassian groups and teams, PagerDuty and Opsgenie / JSM Ops, Linear and Zoom.
- Preview before any change. Before the first sync, it shows exactly who will be added and removed. That preview is also a drift report for the group.
- Recommended actions. It diffs your existing groups and suggests pairs that look like they should match, which is useful when you don't know how many copies of
engineeringyou have. - Permanent users and exclusions. Exceptions are configured, named and visible, not hidden as manual edits.
- Audit logs and notifications. Sync operations are logged, and
@SyncMyGroups subscribe <team>posts every add and remove to a Slack or Microsoft Teams channel.
On the security side, SyncMyGroup is ISO/IEC 27001:2022 certified, encrypts data at rest with AES-256 and in transit with TLS 1.3, uses role-based access, and stores only email addresses and OAuth integration data. That's usually the list your own reviewer will ask for.
For the removal side specifically, see offboarding: removing users from groups. For the onboarding side, automating onboarding into Slack groups.
A review that actually closes
Once derived groups are synced, a quarterly review looks like this:
| Step | What you review | Who |
|---|---|---|
| 1 | Source groups (Google / Entra), one per logical group | Group owner |
| 2 | Permanent users and exclusions on each synced group | Group owner + security |
| 3 | Sync log since last review: unexpected adds or removes | Security |
| 4 | Groups that exist in a tool but have no source mapping | IT |
Step 4 is where remaining drift hides: the groups nobody mapped. Each quarter, either map them to a source or delete them.
FAQ
How often should we run access reviews?
ISO 27001:2022 leaves the interval to your own policy; SOC 2 auditors test that you followed whatever you defined. Many teams review privileged access more often than standard access. Continuous sync doesn't remove the need for reviews, but it makes each one much shorter.
Isn't an IdP enough to prevent drift?
An IdP handles accounts and directory groups well. Drift usually lives in tool-local groups the IdP doesn't manage: Slack channels, on-call teams, project groups, groups created by hand before SSO. Those need either SCIM coverage on every tool (often an enterprise-tier feature) or a sync from a directory group.
What's the most common source of drift?
Movers, more than leavers. Offboarding usually triggers some removal process. A team change often adds new access without removing the old.
Does syncing groups count as access review evidence?
The sync log and preview are useful evidence that removals happened and when. They don't replace the review decision itself. Someone still needs to confirm the source groups and exceptions are right.
Run the preview on one group and see how much drift you have. Connect your tools in SyncMyGroup. It's free up to 5 users. See pricing, or book a walkthrough.