A nested group access review answers a question the direct member list cannot: who effectively receives this entitlement once nesting and dynamic rules finish expanding. The group on the application allows Finance-Readers. Finance-Readers contains All-Staff. All-Staff is dynamic. The application owner reviews twelve direct members and misses the company. That is the sample that fails, and it is the access a departing contractor keeps.
Rutagon flattens the graph to a principal, a path, and an entitlement. Reviewers decide with the path visible. Revokes happen at the hop that is actually wrong, not by deleting a top-level group that other systems still need. Decisions are filed in the GRC you already run.
Direct members are not effective access
Microsoft Graph exposes /groups/{id}/members for the next hop and /groups/{id}/transitiveMembers for the expanded set. Transitive membership is the population. Direct membership is the edit point. We store both. A campaign that shows only transitive users, with no path, forces a revoke of the user from a group the reviewer does not control. A campaign that shows only direct members hides the dynamic group two hops down.
Rule-built groups change without a new direct add. If any group on the path has DynamicMembership, the rule text is part of the row. Approving the expanded users and ignoring the rule means tomorrow's hires inherit the entitlement. The Microsoft 365 group access review handles owner and guest decisions on unified groups. This article handles the path between groups, including security groups that are not Teams.
Cycles happen in directories that grew by accretion. Group A contains B and B contains A. A naive walk does not finish. We track visited group ids on the path, record a cycle, and stop that branch. The cycle itself is a finding. Someone has to break it before the effective set is meaningful.
GET /groups/{id}/members?$select=id,displayName
GET /groups/{id}/transitiveMembers?$select=id,displayName,userType
Microsoft documents the expanded read in List group transitive members. We page it and we still compute paths ourselves, because transitive membership does not return the route. The route is what the reviewer needs.
Nested group access review with the path attached
The row a human sees is: entitlement group, principal, path, and whether any hop is dynamic. Example path: user:jordan via Contractors-West via Finance-Readers via Billing-App. The decision is not always "remove Jordan." The decision might be "Contractors-West does not belong inside Finance-Readers." That one revoke fixes every contractor on the west list without touching Jordan's other access.
We classify the recommended hop so the owner is not guessing. If the innermost group is a role group owned by the application, and a broad department group was nested into it, the mistake is the nest. If a single user was added directly to the application group, the mistake is the direct add. The extract suggests the hop. The owner confirms. We do not auto-revoke broad nests without that confirm, because some nests are the design.
Guest users on a transitive path are flagged the same way they are on a direct review. A partner nested in through a vendor group should be obvious in the path. Contractor and vendor access review is the campaign that owns vendor lifecycle. The nested review supplies the effective path so that campaign is not blind.
Revoke is an API remove of the specific membership edge the owner chose. We re-read transitive membership for that principal and entitlement. If the principal is still present, another path remains and the row stays open with the alternate path shown. One path removed is not effective access removed. The second read is the proof we file.
Scope, performance, and the first export
We do not transitive-expand every group in the tenant into one spreadsheet. The population is the entitlement groups that gate in-scope applications: the SaaS apps and internal apps named in the system description. Those groups are few compared with the directory. Expanding the company all-hands group as if it were an application role wastes the review and hides the real grants.
The first export's value is the surprise path. A sync job nested Domain Users or an HR feed group into an admin role group during an integration project. PIM groups assigned as eligible, covered in the Entra PIM access review, can also contain nests. We pass those paths to the PIM campaign when the entitlement is a directory role, so privileged access is not reviewed as if it were a distribution list.
Graph throttling and deep nests make this a batch job with checkpoints. We cap depth and record anything deeper than the cap as "unexpanded" rather than pretending the user list is complete. A silent cap is how effective access lies. The cap we use is documented on the evidence packet.
Dynamic rules that include other dynamic groups are the slowest to explain to a reviewer. We render the rule next to the path in plain text. If the owner cannot explain the rule, the decision is "escalate," not "approve." Approve means a named person accepts that this principal should keep this entitlement through this path.
Evidence
Each decision stores the entitlement, the principal, the path, the hop removed if any, the actor, and the transitive re-read. The packet is filed in the GRC you already run. Your access recertification control points at that packet. Rutagon does not claim the attestation. We build the flatten, the hop-level revoke, and the proof that the principal fell out of the effective set.
Delta runs list new paths since the last decision: a new nest, a rule edit, a new user inside a group that was already approved as a nest. Approving a nest approves the group as a class only when the owner explicitly accepted the class. Otherwise a new user inside an approved broad group is still a new row. We ask that question once per nest so the delta behavior is intentional.
Application assignments that do not use groups, such as a direct app role on a user, are in scope for access review and out of scope for nesting. We keep them in the custom-application extract described in access review for custom applications. Mixing direct app roles into the group path creates rows with an empty path and trains reviewers to skip them.
Frequently Asked Questions
Why is transitive membership not enough on its own?
Transitive membership names the users who end up with access. It does not show which hop to edit. Reviewers need the path so they can remove a bad nest without deleting a group other applications still use. We store the direct edge and the expanded principal.
How do dynamic groups affect the review?
If any group on the path is rule-built, the rule is part of the decision. Approving today's users leaves the rule free to add the next hire. A rule edit after approval shows up as a delta, not as a silent change.
What happens when groups contain each other in a cycle?
The walk records visited group ids and stops the branch when a group repeats. The cycle is a finding with an owner. Effective access for that branch is not attested until the cycle is broken.
Where do you apply the revoke?
On the membership edge the owner selects, then we re-read transitive members. If another path still includes the principal, the row stays open and shows that path. Removing one route is not the same as removing effective access.
Where is the decision filed?
The entitlement, principal, path, hop removed, and the second transitive read go into the GRC you already run. Rutagon builds the extract and the revoke. Your GRC remains the system of record for the auditor.
See what an Access & Credential Governance Diagnostic finds in your environment. Contact Rutagon at rutagon.com/contact, 907-841-8407, or contact@rutagon.com.