ITMarshall Notes

Field notes / Security

Security · Troubleshooting

Windows Active Directory - Investigating Unexpected Security Group Scope Changes

ITMarshall Notes

September 11, 2026

Use AD replication metadata and Security Event 4764 to prove when a security group's scope changed, identify the initiating account, and separate a directory-object change from patching or authentication issues.

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 ... .HostName may surface as an AD property collection. Converting or selecting the first value avoids -Server parameter 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.

Related notes

If this is the kind of mess you are in, get in touch by email. Fixed-scope advisory: itmarshall.ca.