Purpose
Use this when cross-domain permissions or administrative access unexpectedly stop working and a security-group scope change is suspected.
Key distinction
A Windows update can expose authentication or trust problems. It does not normally rewrite a custom AD group's scope. Group scope and security or distribution state are stored in the groupType attribute. Prove whether that attribute changed before treating patching as the cause.
Capture the current group state
Use a specific domain controller and clear any stale PowerShell variable before assigning the group object. If Get-ADGroup fails, do not trust an older value that may still be stored in the variable.
Remove-Variable g -ErrorAction SilentlyContinue
$GroupName = "Example-CrossDomain-Admins"
$DC = "DC01.example.com"
$g = Get-ADGroup -Identity $GroupName `
-Server $DC `
-Properties groupType,whenCreated,whenChanged,member `
-ErrorAction Stop
$g | Format-List Name,DistinguishedName,SID,GroupScope,GroupCategory,groupType,whenCreated,whenChanged
Inspect replication metadata
Get-ADReplicationAttributeMetadata requires a specific domain controller, not merely a domain or forest DNS name.
Get-ADReplicationAttributeMetadata `
-Object $g.DistinguishedName `
-Server $DC |
Where-Object AttributeName -eq "groupType" |
Format-List AttributeName,AttributeValue,Version,LastOriginatingChangeTime,LastOriginatingChangeDirectoryServerIdentity,LastOriginatingChangeUsn
The replication Version is especially useful:
- Version 1 means no originating write to that attribute after initial creation.
- Version 2 means one later originating write.
- Version 3 or higher proves multiple writes occurred.
Do not assume every version increment was a scope conversion. The groupType attribute also includes the security or distribution flag, and an attribute can theoretically be rewritten with an equivalent value.
Check all DCs before replication converges
If someone has just corrected the group, query every DC immediately. A lagging DC may still expose the prior version and prior scope.
$SeedDC = "DC01.example.com"
$GroupName = "Example-CrossDomain-Admins"
$results = foreach ($d in Get-ADDomainController -Filter * -Server $SeedDC) {
$server = [string]($d.HostName | Select-Object -First 1)
try {
$grp = Get-ADGroup -Identity $GroupName -Server $server -Properties groupType,whenChanged
$meta = Get-ADReplicationAttributeMetadata -Object $grp.DistinguishedName -Server $server |
Where-Object AttributeName -eq "groupType"
[pscustomobject]@{
QueriedDC = $server
Scope = $grp.GroupScope
Category = $grp.GroupCategory
groupType = $grp.groupType
Version = $meta.Version
LastOriginatingChange = $meta.LastOriginatingChangeTime
OriginatingDSA = ($meta.LastOriginatingChangeDirectoryServerIdentity -join ";")
LastOriginatingUSN = ($meta.LastOriginatingChangeUsn -join ";")
LocalUSN = ($meta.LocalChangeUsn -join ";")
}
}
catch {
[pscustomobject]@{
QueriedDC = $server
Scope = "ERROR"
Category = $_.Exception.Message
}
}
}
$results | Sort-Object QueriedDC | Format-Table -Auto
Use Security Event 4764 for attribution
Event 4764 is the most useful audit record for this case because it records a group-type or scope change, the account that initiated it, and the old and new group type.
$GroupName = "Example-CrossDomain-Admins"
$SeedDC = "DC01.example.com"
$StartTime = (Get-Date).AddMonths(-6)
$events = foreach ($d in Get-ADDomainController -Filter * -Server $SeedDC) {
$server = [string]($d.HostName | Select-Object -First 1)
Get-WinEvent -ComputerName $server -FilterHashtable @{
LogName = 'Security'
Id = 4764
StartTime = $StartTime
} -ErrorAction SilentlyContinue | ForEach-Object {
$event = $_
$xml = [xml]$event.ToXml()
$data = @{}
foreach ($item in $xml.Event.EventData.Data) {
$data[$item.Name] = [string]$item.'#text'
}
if ($data.TargetUserName -eq $GroupName) {
[pscustomobject]@{
TimeCreated = $event.TimeCreated
DC = $event.MachineName
ChangedBy = "$($data.SubjectDomainName)\$($data.SubjectUserName)"
Change = $data.GroupTypeChange
Group = $data.TargetUserName
LogonId = $data.SubjectLogonId
RecordId = $event.RecordId
}
}
}
}
$events | Sort-Object TimeCreated | Format-List TimeCreated,DC,ChangedBy,Change,Group,LogonId,RecordId
Scope interpretation
For security-enabled groups, common groupType values are:
-2147483646 = Global Security
-2147483644 = Domain Local Security
-2147483640 = Universal Security
A Domain Local group can be used to assign permissions only within the domain in which that group exists. Converting a cross-domain administrative group from Universal or Global to Domain Local can therefore break permissions in another trusted domain even though membership and trust relationships are otherwise unchanged.
Validation
After restoring the intended scope, verify the actual permission path on a representative resource. Check the target system's local Administrators group or relevant domain-local resource group, then refresh Kerberos tickets or start a new logon session before retesting.
Catches / gotchas
- A failed assignment such as
$g = Get-ADGroup ...does not necessarily clear a previously populated$g. Remove or overwrite the variable deliberately before interpreting output. Get-ADDomainController ... .HostNamemay surface as an AD property collection. Converting or selecting the first value avoids-Serverparameter binding failures.- Replication metadata shows only the current replicated version and latest originating write, not the complete value history.
- After a corrective change has replicated to all DCs, the prior scope cannot be recovered from a stale DC. Use Event 4764 to reconstruct the transition.
- Broad client-side scans of Event 5136 over months of Security logs can be very slow on busy DCs. Prefer 4764 for group scope or type changes and narrow any 5136 query aggressively.
Key lesson
When cross-domain access unexpectedly disappears around a maintenance window, first prove whether the AD authorization object changed. Replication metadata establishes that groupType was written and identifies the originating DC and time. Event 4764 establishes who changed it and the exact scope transition.