What we independently observed
The test machine contained the current user's 16-hex-digit LID under IdentityCRL\ExtendedProperties. That exact value also appeared as the value name under the current-user Immersive Property key and in all six current-user Immersive Token DeviceId values inspected.
Additional populated IdentityCRL state existed under HKEY_USERS\.DEFAULT and HKEY_USERS\S-1-5-18 (SYSTEM), including ExtendedProperties, Immersive Property, and Immersive Token records. Those SYSTEM-context identifiers were not the same value as the signed-in user's LID on this machine.
We also confirmed the presence of machine-level NegativeCache, ThrottleCache, and IdentityStore\Providers trees. This establishes that the local identity state is broader than one HKCU value.
What this does not establish
Presence is not proof of purpose. This read-only check does not, by itself, prove which copy is authoritative, which copy can recreate another, which service wrote each record, or whether every identifier is transmitted as a GDID.
deGDID reports controlled VM experiments involving anonymous minting, persistence, protection, and reminting. Windows-GDID-Changer reports a destructive remint procedure. Those are valuable, testable leads; we will label them as external findings until Source Potato reproduces the behavior in a disposable VM.
Likewise, service and endpoint associations reported by community mitigation projects are investigative context—not automatic proof that a particular request contained GDID.
The local state is separated by security context.
Observed by Source Potato: the signed-in user, .DEFAULT, and SYSTEM contained populated identity state, and the SYSTEM-context values inspected were not the same as the signed-in user's LID. Current-user Immersive Property and Token records repeated the current-user value, while machine-level IdentityCRL trees contained additional caches and provider state.
Reported by the original researchers: one Windows installation can hold multiple device PUIDs associated with different security contexts. Their follow-up work also reports a user-context Windows component transmitting a SYSTEM-associated device PUID. We have confirmed the existence of distinct contexts locally, but we have not independently reproduced every selection and switching behavior described upstream.
This is why “one permanent ID per PC” is too simple. The evidence supports a set of related identity records whose selected value can depend on the Windows component, token, account state, and security context involved.
Known local surfaces, without exposing their values
IdentityCRL\NegativeCache: machine-level PUID/SID records; the decimal conversion of one locally stored device PUID matched our transmitted GDID.
IdentityCRL\ExtendedProperties: populated user and SYSTEM-context identity properties, including LID state.
- Immersive
Property and Token records: repeated device-identity state associated with the corresponding context.
IdentityCRL\ThrottleCache and IdentityStore\Providers: supporting machine-level identity trees whose presence we confirmed but whose complete roles are not established by a read-only inventory.
- Windows Push Notification state: GDID-named cache keys and
DeviceVersionRepresentation identified by two independent community implementations as part of device-registration refresh behavior.
Paths and field names are published because they are necessary for independent verification. Every raw value, SID-bearing record name, and participant-specific identifier remains withheld.
July 23 follow-up
New scripts point to Windows Push Notification identity state.
A new project, Metrix187’s paws-off-my-gdid, separates a quiet local HKCU substitution from a much more disruptive attempt to make Windows request a fresh server-issued device identifier. Its source adds backup, restore, dry-run, and managed-device safeguards around changes to SYSTEM-context IdentityCRL and Windows Push Notification state.
On the same day, Windows-GDID-Changer added a Push Notification cache reset. Both projects identify HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\PushNotifications\<old GDID> and DeviceInfo\DeviceVersionRepresentation as state involved when refreshing a device registration.
Why this matters to our work: two independently published implementations now give us exact registry surfaces and service activity to observe during a controlled test. They may help us trigger and recognize identity lifecycle events in GDID Usage Discovery.
What remains unproven: deleting local state, changing the presented value, or receiving a new server-issued value does not establish that Microsoft cannot correlate the old and new records through account, certificate, hardware, network, or other machine information. We have reviewed these scripts but have not executed their destructive operations. They are test leads, not privacy guarantees.
July 24 validation
Microsoft directly connects GDID assignment, wlidsvc, and Windows Update registration.
Microsoft’s Intune feature-update troubleshooting documentation defines DeviceRegistrationInvalidGlobalDeviceId as a failure to register or authenticate with Windows Update because of an invalid Global Device ID. Microsoft says an unavailable Microsoft Account Sign-In Assistant service may prevent Global Device ID assignment and recommends making that service able to run.
This is important first-party corroboration. It independently supports the reverse-engineered role of wlidsvc, establishes that GDID participates in Windows Update registration or authentication, and explains why disabling identity services can damage ordinary update functionality. It does not disclose every service that receives GDID or every field transmitted beside it.
Changing the visible LID does not change the complete identity.
ZeroTrace Lab’s live patching experiments, using the implementation published by 5mukx in GDID-Extractor, separate four layers: the plaintext registry LID, a DPAPI-protected DeviceTicket containing a Microsoft-signed certificate and PUID, hardware descriptors, and Microsoft’s server-side record.
Replacing only the plaintext LID changes what a local registry reader reports. The DeviceTicket still presents the original certificate-backed identity when wlidsvc authenticates again, and the visible value can revert. This experimentally supports treating registry-only “rotation” as a cosmetic local substitution, not a demonstrated change to Microsoft’s authoritative identity or historical records.
Claims about the exact hardware inputs and Microsoft’s server-side linkage remain partly inferred because the backend cannot be inspected from the client.
Blocking attempts can fail silently or break Windows features.
A detailed field report against gdid-privacy identified reproducible firewall-rule construction defects, success messages printed after failed rule creation, rapidly changing Microsoft endpoint addresses, and elevated scheduled tasks launched from a user-writable path. A separate Windows 10 report shows its rotated value immediately returning to the original GDID.
An updated no-gdid compatibility report describes Windows Update, Microsoft Store updates, and DISM source retrieval failing after relevant services were disabled on Windows 11 Pro 25H2 build 26200.8875. That is a community report rather than a controlled Microsoft test, but it is consistent with Microsoft’s own update-registration documentation.
Practical conclusion: a tool saying “blocked” or “rotated” is not evidence. A defensible mitigation requires before-and-after capture, correct rule verification, functionality testing, and proof that the server-observed identity changed or disappeared.
July 25 community update
Disabling CDP is now one project’s default, but its broadest claim exceeds the evidence.
David Swan changed gdid-privacy so blockCDP defaults to enabled. The change disables CDPSvc and CDPUserSvc and explicitly warns that Nearby Share, cross-device clipboard, and Continue on PC will stop working.
The project also says this makes the real GDID “never reported” and eliminates the tracking vector entirely. We cannot validate that universal claim. Our controlled capture below used Windows Content Delivery Manager and backgroundTaskHost.exe to send a locally matched GDID to the IRIS service. That demonstrated path is distinct from merely observing CDP/DDS traffic.
Evidence-based interpretation: disabling CDP may block or disrupt a documented part of the identity ecosystem. Only a controlled before-and-after test across each known sender can establish which transmissions it actually prevents.
A newly posted remediation script is a proposal, not proof.
A July 24 script posted to the foundational repository disables CDP and Microsoft Account services, deletes local identity state, changes Activity Feed policies, and blocks a domain list. It does not include a before-and-after GDID-bearing capture proving that every transmission path stops, and its rollback cannot recreate every identity artifact it deletes.
We therefore classify it as an unverified and potentially disruptive community experiment. We have not executed it, and its presence in an issue on the original research repository does not make it an endorsed fix.
New public coverage, but not new primary evidence
Neowin’s July 23 overview, IBTimes UK’s July 23 coverage, and Lenta.ru’s July 24 report expanded public awareness but did not add a new packet capture, binary trace, Microsoft disclosure, or court filing. They largely restate the federal complaint, prior reporting, and community reverse engineering.
Some public summaries continue to describe one identifier per PC; the evidence reviewed here instead supports multiple device PUID/GDID values associated with different security contexts on one Windows installation.
Publication date and popularity do not turn a summary into independent technical confirmation. Our evidence hierarchy continues to place court records, captured request data, reproducible local observations, and source-level analysis above derivative news coverage.
Before modern GDID
Microsoft Passport and Windows Live used persistent PUIDs for accounts before current versions of Windows. This is the identity family from which device PUIDs developed, but an old account PUID is not by itself proof of the modern Windows-installation GDID or its transmission.
Windows 7 is not established
A Hybrid Analysis report executes a wlidsvc.dll sample inside a Windows 7 SP1 build 7601 guest, but the file metadata identifies the sample itself as Windows 10 version 1803, file version 10.0.17134.523. The guest operating system is the analysis environment, not the sample's provenance. This artifact therefore cannot establish DevicePUID or modern GDID behavior in Windows 7.
Windows 8 remains an open boundary
Windows 8 made Microsoft Accounts a first-class Windows sign-in, and publicly preserved 2013 registry material contains IdentityCRL device identities and certificates. We have not yet established the originating Windows edition and build strongly enough, nor located a period request containing the exact modern GLOBALDEVICEID field. It remains a historical lead rather than a dated GDID finding.
Windows 10 built the recognizable modern path.
Indexed Windows binaries show that cdp.dll shipped in the base Windows 10 version 1507 image, build 10240, with file version 10.0.10240.16384. Historical service records describe CDPSvc as present but disabled by default in Windows 10 version 1511, build 10586, and automatic by default in Windows 10 version 1607, build 14393. Its role is to authenticate users and devices and connect them through local or cloud-backed device scenarios. Together with wlidsvc, IdentityCRL, DDS, Windows reporting, and Microsoft content services, this is the earliest Windows generation whose architecture closely resembles the GDID system under current investigation.
This supports a cautious conclusion that the present cross-service infrastructure took shape during the Windows 10 rollout, not that every Windows 10 component or request necessarily carried GDID.
By 2020, transmission is independently preserved.
The earliest outgoing evidence we have located was recorded on November 24, 2020 in a Windows 10 version 1803 environment. Both the sandbox description and request metadata identify OS build 17134.1. The request contains a decimal GLOBALDEVICEID in an MSN/IRIS impression pattern. Separate December 2021 and January 2022 captures preserve the same field and request family on the same version 1803/build 17134.1 test baseline. These artifacts predate the 2026 public controversy and were generated independently of our investigation.
Microsoft's later Managed Desktop API and Windows Update reporting schemas show globalDeviceId or GlobalDeviceId as an established device-record field. The archived API placed it beside device, tenant, assigned-user, operating-system, management, and compliance information. That proves broad internal record context; it does not prove every GDID-bearing request included every neighboring field.
Commercial availability and technical evidence timeline
The same Windows build can have several historically meaningful dates. Availability rows explain when it reached manufacturers, consumers, and independent PC builders. Technical rows explain what GDID-related evidence exists. Shipping a component is not treated as proof that it transmitted an identifier.
GDID-specific control: we found general controls for Microsoft Account connections, wlidsvc, CDPSvc, and diagnostic-data levels, but no reviewed Windows release documents a user-facing choice specifically naming GDID, Device PUID, or GLOBALDEVICEID. “Disabled by default” below describes a service configuration, not informed consent. “Diagnostic data reduced” is not treated as proof that GDID transmission stops.
- Windows release
- Windows 10 version 1507, build 10240
- GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. Microsoft Account connections were allowed by default; this is not proof that GDID transmission was active.
- What it establishes
- Manufacturers could validate and prepare the final Windows 10 commercial build for new PCs.
- Windows release
- Windows 10 version 1507, build 10240
- GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. Launch setup provided no separate GDID disclosure or consent prompt.
- What it establishes
- The original Windows 10 release became publicly obtainable and began shipping on retail computers.
OEM/System Builder product for local shops and PC integrators
- Windows release
- Windows 10 version 1507, build 10240
- GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. The System Builder channel did not create a different GDID control model.
- What it establishes
- Independent computer builders could commercially license the same Windows generation for newly assembled PCs.
- Windows release
- Windows 10 version 1507, build 10240;
cdp.dll 10.0.10240.16384 - GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. Component presence does not reveal whether a particular scenario was enabled or invoked.
- What it establishes
- The supporting CDP code existed in the first commercially released Windows 10 image. This does not prove a GDID-bearing transmission.
November Update; CDPSvc disabled by default
- Windows release
- Windows 10 version 1511, build 10586
- GDID control/default
- CDPSvc was disabled by default; no GDID-specific opt-in or opt-out was presented to users. The service state was not informed consent and does not establish the state of other identity or reporting paths.
- What it establishes
- The service existed but was not broadly enabled in the default configuration.
Anniversary Update; CDPSvc automatic by default
- Windows release
- Windows 10 version 1607, build 14393
- GDID control/default
- CDPSvc was automatic by default; no GDID-specific opt-in or opt-out was presented to users. Enterprise controls could restrict some Microsoft Account behavior, but that was not a disclosed GDID control.
- What it establishes
- The platform became part of the default operating-system service configuration.
April 2018 Update; Device-PUID binary examined
- Windows release
- Windows 10 version 1803, build 17134;
wlidsvc.dll 10.0.17134.523 - GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. Users could lower general diagnostic-data settings and administrators could disable Microsoft Account Sign-in Assistant, but neither was disclosed as a GDID control or is proven here to eliminate GDID.
- What it establishes
- The binary contains DevicePUID and related identity machinery. Its Windows 7 sandbox guest does not make it a Windows 7 binary.
Earliest preserved outgoing GLOBALDEVICEID field located
- Windows release
- Windows 10 version 1803, build 17134.1
- GDID control/default
- Capture's privacy-setting state is unknown. The background request proves transmission in that environment, not which general setting permitted or prevented it.
- What it establishes
- An independently archived MSN/IRIS request contains the exact
GLOBALDEVICEID field.
Additional independently preserved transmissions
- Windows release
- Windows 10 version 1803, build 17134.1
- GDID control/default
- Capture settings are unknown. No user action or GDID-specific consent step is preserved in the reports.
- What it establishes
- The same field and request family recur in later, separately preserved analyses.
Foundational public reverse engineering
- Windows release
- Windows 11 build 26200
- GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. The research reports an anonymous/no-Microsoft-account path as well as account-backed identity state.
- What it establishes
- Public-symbol and live ETW work traced the modern component and identity chain.
Source Potato reproduction
- Windows release
- Windows 11 build 26200.8875
- GDID control/default
- No GDID-specific opt-in or opt-out was presented to users. General Windows privacy settings did not provide a disclosed GDID switch; our test observed background transmission.
- What it establishes
- Our local ETW capture matched transmitted decimal GDID to locally stored IdentityCRL/PUID state.
System Builder/OEM product reached resellers through a commercial distribution channel rather than one universal worldwide shelf date. The timeline therefore identifies the 2015 launch period without asserting an unsupported day for every region or distributor.
The earliest defensible statement
The earliest version boundary currently supported for the recognizable GDID infrastructure is Windows 10. The CDP binary shipped in version 1507/build 10240, CDPSvc was disabled by default in version 1511/build 10586, and it became automatic by default in version 1607/build 14393. The earliest preserved outgoing GLOBALDEVICEID evidence we have located is Windows 10 version 1803/build 17134.1 on November 24, 2020.
We have not found sufficient evidence to claim that Windows 7 transmitted the modern field, to assign Windows 8 a defensible GDID build, to identify one exact collection start date, or to show that the complete present-day correlation capability existed in every earlier version. Establishing an earlier transmission date requires a period-correct binary or installation plus preserved network or ETW evidence—not a filename, registry name, or sandbox guest label alone.
Three IRIS requests
microsoft.windows.contentdeliverymanager_cw5n1h2txyewy constructed three requests addressed to:
ris.api.iris.microsoft.com/v1/a/impression
Alongside GDID, the observed field names included content, audience, placement, local-device, advertising, personalization, request, session, event-time, Windows version, OEM, and experiment/feature-flight values.
One MSN ARC request
MicrosoftWindows.Client.CBS_cw5n1h2txyewy constructed one request addressed to:
arc.msn.com/v3/Delivery/Events/Impression
That request contained GDID twice and included more than 100 named parameters describing the machine, its Windows environment, network context, content event, preferences, and other correlation-capable identifiers.
Identity and correlation
GLOBALDEVICEID, ANID, ASID, CID, ID, LOCALID, PERSID, REQASID, DS_EVTID, and MAP_TID.
Hardware and system
OEM and model, processor and vendor, logical processor count, architecture, RAM, disk capacity and free space, graphics capability, display dimensions, monitor count, Windows edition, build, branch, and device family.
Network and experience
Public IP address, country, locale, language, retail flight ring, feature experiments, opt-out and advertising state, content placement, impression identifiers, and request time.
Why the local match matters
The captured decimal GDID and the decimal conversion of a 16-character hexadecimal PUID stored beneath HKLM\SOFTWARE\Microsoft\IdentityCRL\NegativeCache produced the same complete SHA-256 digest. That establishes a match between the transmitted value and locally stored Windows identity state without publishing either value.
Privacy note: this public account intentionally omits the raw GDID/PUID, public IP, account identifiers, exact machine model, evidence timestamps, temporary process IDs, and other values that could point back to the test computer or its owner. Field names, counts, packages, destinations, methods, and non-identifying conclusions are retained.
The four logical requests, in sanitized sequence
The searchable portion of the unattended capture contained three closely grouped Content Delivery Manager impression requests to the IRIS endpoint, followed later by one Client CBS impression request to MSN ARC. We publish the order, package identities, destinations, and logical request count while withholding exact timestamps, temporary process IDs, request/session identifiers, and the identifier values themselves.
- Content Delivery Manager →
ris.api.iris.microsoft.com/v1/a/impression
- Content Delivery Manager →
ris.api.iris.microsoft.com/v1/a/impression
- Content Delivery Manager →
ris.api.iris.microsoft.com/v1/a/impression
- Microsoft Windows Client CBS →
arc.msn.com/v3/Delivery/Events/Impression
The unattended state matters: no person needed to open a browser or intentionally visit either endpoint during the recorded activity. It does not establish that every idle Windows computer will produce the same requests on the same schedule.
What we observed in the component chain
IdentityCRL supplied locally stored identity state. Windows packages constructed GDID-bearing request operations, and WinINet diagnostic events exposed the request data before HTTPS encryption. Package attribution tied the IRIS operations to Content Delivery Manager and the ARC operation to Client CBS.
That is the directly observed portion of our evidence chain. An executable host name such as backgroundTaskHost.exe is not sufficient attribution by itself; the hosted package and process context are necessary.
What upstream work adds
The original reverse engineering associates wlidsvc, IdentityCRL helpers, Connected Devices Platform (CDP), and Device Directory Services (DDS) with device-identity creation, lookup, transport, or synchronization. Community work adds Windows Push Notification registration state to the lifecycle picture.
Those associations are valuable technical evidence, but our request capture did not independently execute and prove every internal call in that complete chain. We preserve the distinction between our dynamic observation and externally reported internals.
GDID is not every other identifier beside it.
GLOBALDEVICEID was the field we matched to local PUID state. LOCALID, ANID, PERSID, session/request IDs, advertising values, and other opaque fields accompanied it but are not automatically alternative names for GDID. Their ability to correlate activity may still matter even when their undocumented semantics remain unknown.
Microsoft's separately documented SQM MachineId is another durable Windows identifier stored under SQMClient; it should not be conflated with the IdentityCRL PUID/GDID family. Likewise, a Store-style identifier or a GUID-shaped local value is not a GDID merely because it is persistent.
The behavior predates the current public investigation.
Independent pre-2026 sandbox and privacy-analysis artifacts contain the same GLOBALDEVICEID field and IRIS/MSN impression patterns. Those historical records corroborate that the request behavior was not introduced for this investigation or created by our test. They do not prove which local PUID supplied every historical value.
Before beginning: set up one private working folder
You do not need to install PowerShell or download a packet-capture program. These commands use tools included with Windows. The test does require administrator access.
- Open the Start menu and type Windows PowerShell.
- Right-click Windows PowerShell, choose Run as administrator, and approve the Windows security prompt.
- Copy the setup block below, paste it into the blue PowerShell window, and press Enter.
- Close unrelated applications if you want a quieter trace.
- Plan to leave the machine idle for several hours or overnight.
$workFolder = Join-Path $env:USERPROFILE 'Desktop\GDID-Reproduction'
New-Item -ItemType Directory -Force -Path $workFolder | Out-Null
Set-Location $workFolder
"Working folder: $((Get-Location).Path)"
"Administrator: $([Security.Principal.WindowsPrincipal]::new(
[Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))"
Expected result: PowerShell prints a folder ending in Desktop\GDID-Reproduction and Administrator: True. If it says False, close the window and reopen PowerShell using Run as administrator.
Keep this same PowerShell window open through the start step. The later stop commands use the session's explicit name, so the trace can still be stopped from a new elevated PowerShell window if Windows restarts the terminal.
1. Record privacy-preserving hashes of candidate local PUIDs
This writes only each candidate's four-character class prefix and the SHA-256 hash of its decimal representation. It does not write the SID or raw PUID.
$candidateHashes = @()
$path = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IdentityCRL\NegativeCache'
if (Test-Path $path) {
Get-ChildItem $path -ErrorAction SilentlyContinue | ForEach-Object {
if ($_.PSChildName -match '^(?<puid>[0-9A-Fa-f]{16})_S-.+$') {
try {
$decimal = [Convert]::ToUInt64($Matches.puid, 16).ToString()
$sha = [Security.Cryptography.SHA256]::Create()
try {
$digest = ([BitConverter]::ToString(
$sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($decimal))
)).Replace('-', '')
} finally { $sha.Dispose() }
$candidateHashes += [pscustomobject]@{
Prefix = $Matches.puid.Substring(0, 4)
DecimalSHA256 = $digest
}
} catch {}
}
}
}
$candidateHashes | ConvertTo-Json |
Set-Content '.\local-id-hashes.json' -Encoding UTF8
"Candidate local identifiers recorded: $($candidateHashes.Count)"
Get-Item '.\local-id-hashes.json' | Select-Object Name, Length
Expected result: the command reports one or more candidate identifiers and shows a small file named local-id-hashes.json. A result of zero is possible on some systems, but it means this procedure will not be able to prove the local-value match even if a network request is later found.
2. Start a client-side network trace
The circular trace is limited to 256 MB. It enables the Windows WinINet and WinHTTP ETW providers.
$session = 'GDID-Public-Reproduction'
logman create trace $session -ow -o '.\gdid-user.etl' -f bincirc -max 256 -ets
# Microsoft-Windows-WinINet
logman update trace $session `
-p '{43D1A55C-76D6-4F7E-995C-64C711E5CAFE}' 0xFFFFFFFFFFFFFFFF 0xFF -ets
# Microsoft-Windows-WinHttp
logman update trace $session `
-p '{7D44233D-3055-4B9C-BA64-0D47CA40A232}' 0xFFFFFFFFFFFFFFFF 0xFF -ets
logman query $session -ets
Expected result: each setup command prints The command completed successfully. The final query should list GDID-Public-Reproduction with a running status and show the two provider GUIDs.
If Windows reports that the data collector already exists, run the cleanup block under Troubleshooting and safe cleanup, then repeat this step.
Leave the machine idle. If you deliberately open Windows content surfaces such as Widgets, Start recommendations, or Windows Backup prompts, write down the time so you can distinguish those actions from unattended behavior.
3. Stop and export
Return to an elevated PowerShell window after the observation period. If this is a new window, run the first three setup lines again to return to the correct folder. Then paste this block:
$workFolder = Join-Path $env:USERPROFILE 'Desktop\GDID-Reproduction'
Set-Location $workFolder
logman stop 'GDID-Public-Reproduction' -ets
logman delete 'GDID-Public-Reproduction'
tracerpt '.\gdid-user.etl' -of XML -o '.\gdid-user.xml' -y
Expected result: the stop and delete commands complete successfully. tracerpt reaches 100 percent and creates gdid-user.xml. The XML may be much larger than the original ETL file; that is normal.
Get-Item '.\gdid-user.etl', '.\gdid-user.xml', '.\local-id-hashes.json' |
Select-Object Name, Length, LastWriteTime
All three files should be listed. Keep them private.
4. Find candidate requests without printing their private values
Paste the complete block below. It reads the XML, finds absolute HTTP or HTTPS URLs containing a decimal GLOBALDEVICEID, and prints only the destination, identifier length, and parameter names. It keeps the raw identifier in memory for the next validation step but does not display it.
$xmlText = Get-Content '.\gdid-user.xml' -Raw
$pattern = '(?i)(?<url>https?://[^\s"<>]*?GLOBALDEVICEID=(?<id>[0-9]{8,20})[^\s"<>]*)'
$urlMatches = [regex]::Matches($xmlText, $pattern)
$candidateRequests = foreach ($match in $urlMatches) {
$decodedUrl = [Net.WebUtility]::HtmlDecode($match.Groups['url'].Value)
try {
$uri = [Uri]$decodedUrl
$fieldNames = [regex]::Matches($uri.Query, '(?:^|[?&])([^=&]+)=') |
ForEach-Object {
[Net.WebUtility]::UrlDecode($_.Groups[1].Value)
} | Sort-Object -Unique
[pscustomobject]@{
Destination = $uri.Host + $uri.AbsolutePath
GDIDLength = $match.Groups['id'].Value.Length
Fields = $fieldNames -join ', '
PrivateGDID = $match.Groups['id'].Value
}
} catch {}
}
"Raw matching URL records: $($candidateRequests.Count)"
$candidateRequests |
Select-Object Destination, GDIDLength, Fields -Unique |
Format-List
Expected result when activity was captured: the count is greater than zero and at least one block lists a destination and GDIDLength. Multiple raw records may describe the same logical request, so the raw count is not a reliable count of separate transmissions.
If the count is zero: first confirm that gdid-user.xml is not empty. If it contains data, the machine simply may not have produced a matching request during this window. Repeat a longer capture. A zero result does not show that the computer never sends GDID.
5. Automatically validate the local-to-transmitted relationship
Run this block in the same PowerShell window immediately after step 4. It hashes every distinct captured GDID in memory and compares those hashes with the local inventory. It prints no raw identifier.
if (-not $candidateRequests -or $candidateRequests.Count -eq 0) {
Write-Warning 'No candidate request is available to validate.'
return
}
$inventory = @(Get-Content '.\local-id-hashes.json' -Raw | ConvertFrom-Json)
$validation = foreach ($observedGdid in (
$candidateRequests.PrivateGDID | Sort-Object -Unique
)) {
$sha = [Security.Cryptography.SHA256]::Create()
try {
$digest = ([BitConverter]::ToString(
$sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($observedGdid))
)).Replace('-', '')
} finally { $sha.Dispose() }
[pscustomobject]@{
GDIDLength = $observedGdid.Length
GDIDSHA256 = $digest
MatchesLocalDecimalPUID = [bool](
$inventory.DecimalSHA256 -contains $digest
)
}
}
$validation | Format-List
$candidateRequests = $null
$observedGdid = $null
$xmlText = $null
The core result is reproduced when: at least one result says MatchesLocalDecimalPUID: True. The destination printed in step 4 identifies where that GDID-bearing request was addressed. Save the hashes and redacted output if you want to report the reproduction; do not publish the XML or raw URL.
Troubleshooting and safe cleanup
- Access is denied: close PowerShell and reopen it with Run as administrator.
- The collector already exists: use the cleanup block below, then repeat the start step.
tracerpt cannot find the ETL: run the working-folder setup again and confirm that gdid-user.etl exists with Get-ChildItem.
- No candidate local identifiers: the trace can still find transmissions, but this specific procedure cannot prove their relationship to local IdentityCRL state.
- No matching requests: collect longer. Our unattended result did not appear on demand, and different Windows versions, accounts, settings, regions, and feature states may behave differently.
This cleanup is safe to run after an interrupted attempt. Errors saying the collector does not exist can be ignored.
logman stop 'GDID-Public-Reproduction' -ets
logman delete 'GDID-Public-Reproduction'
# Confirm that the named trace is no longer running.
logman query -ets | Select-String 'GDID-Public-Reproduction'
If the final command prints nothing, the named trace is no longer active. Deleting the GDID-Reproduction folder later removes the local test files; do that only after you have finished reviewing or preserving your evidence.
A successful reproduction
- A WinINet or WinHTTP event contains an absolute request URL with a
GLOBALDEVICEID field.
- The hostname and path come from that same captured event.
- The complete SHA-256 digest of the transmitted decimal value matches the digest of a locally inventoried hexadecimal PUID after unsigned decimal conversion.
- The original ETL is retained privately so the redacted result remains auditable.
The native procedure establishes request construction, destination/path, field presence, and local-value equivalence. Exact process/package attribution requires structured ETW parsing and careful timestamp/PID correlation, which our collector automates.
Potentially sensitive means potentially sensitive
A submitted event may contain public or private IP addresses, machine and account identifiers, usernames, URLs, request parameters, hardware details, process command lines, file paths, handles, package information, tokens, content fragments, or other confidential material present in the captured event and its immediate attribution context.
We do not want passwords, financial information, health information, addresses, private communications, legal material, or other privileged or highly personal content. But if a GDID-bearing operation contains or exposes such material, preserving the complete evidence is part of determining what the observed software collected or transmitted. Reporting should be enabled only with that understanding.
What we do not claim
Opting in does not authorize indiscriminate collection of unrelated documents, browsing history, keystrokes, clipboard contents, passwords, or arbitrary files. The collector is aimed at exact identifier events and the evidence needed to understand them.
However, no static list can promise what an unknown future event will contain. If sensitive material is embedded in the triggering event, request, process context, or related evidence we capture, it may be submitted and visible to authorized researchers until the participant deletes it.
Our privacy and security commitment—and its honest limit
We will make every reasonable effort to minimize unnecessary collection, restrict researcher access, protect credentials, secure data in transit and at rest, log administrative access, isolate participant records, honor deletion requests, and remove personal values from public reports. Public findings will use redacted, aggregated, or otherwise de-identified evidence unless a participant has knowingly agreed to a different use.
We cannot promise zero risk. No internet-connected service, database, software system, administrator, or security control is infallible. Vulnerabilities, mistakes, credential theft, insider abuse, legal demands, service failures, and data breaches can happen. Participation is optional precisely because contributing complete evidence carries a real privacy risk. We will be candid about that risk, respond seriously to incidents, and never describe “best effort” security as a guarantee.
Continuing work
This page is a checkpoint, not the end of the investigation.
Our current collector prioritizes exact local GDID/PUID representations, preserves the triggering event first, then gathers process lineage, command line, executable identity, package context, sockets, handles, modules, signatures, and nearby activity on a best-effort basis. It explicitly excludes its own reads and reporting traffic so the observer does not become its own evidence.
As new event shapes appear, we will preserve more evidence first and narrow the routine capture only after the pattern is understood. Public findings will continue to distinguish directly captured facts, time/process correlation, external attribution, and unanswered questions.