Research · Defensive guidance

Detecting passkey trust downgrade from WebAuthn to cloud session

Last reviewed:

A passkey assertion can be cryptographically valid even when no genuine user verification occurred or device-enrolment trust was abused; correlate endpoint evidence, the WebAuthn ceremony and a deliberately linked cloud session.

In this research
  1. Contribution
  2. The pattern
  3. Why it matters to cloud defenders
  4. ATT&CK mapping
  5. Detection guidance
  6. What to do now
Research snapshot
Type
Defensive guidance
Reviewed
2026-08-04
ATT&CK
T1555.003, T1556.006, T1078.004

Contribution

This post adds an end-to-end detection contract for passkey trust downgrade: join endpoint evidence that a synced passkey store or device-enrolment state was touched, the relying party's record of what WebAuthn requested and accepted, and the first cloud or SaaS session linked through a federation transaction identifier. The contribution is detection content, including explicit normalised event shapes and separate correlations for UV-false validation failure and UV-true device-trust replacement. Both refuse to invent a shared session ID when the evidence planes cannot be joined.

The pattern

Passkeys remove the reusable secret from a sign-in, but they do not remove trust decisions. A relying party still decides whether user verification is required. A browser and its passkey provider still decide how a device proves that it is trusted. The server still has to inspect the signed authenticator data rather than assume the client honoured the request.

Unit 42's Pass-ta-key research shows why those distinctions matter. Its tests focused on Google Password Manager in Chrome on TPM-equipped Windows systems. The attacks require malware already running as the user, so this is not a remote passkey break. From that foothold, however, the researchers found three paths with different consequences.

The first path reads Chrome's local passkey metadata and a wrapped device identity key. Malware can ask the TPM to sign with that wrapped key without elevation or a device-unlock prompt. The resulting assertion is cryptographically valid but has the WebAuthn User Verified flag, normally called UV, unset. A relying party that requested user verification but fails to check the returned flag can issue a session anyway. Unit 42 reported that gap to affected relying parties and says eBay fixed the behaviour after disclosure.

The second path targets device onboarding. By forcing re-enrolment and exploiting a pending user-verification-key state, the attacker can register a public key they control as the device's UV key. Assertions signed by that key then carry UV as true, so a relying party cannot separate them from assertions produced after a genuine local unlock. The third path recovers the security-domain secret used to protect synced passkeys. Unit 42 found that secret in Chrome logging during registration, and says Google removed it from the log after disclosure. The research also found the secret still present in Chrome process memory during recovery, which permits extraction of synced private keys from a compromised endpoint.

The recovery boundary for that third path is unusually important. In the Google implementation Unit 42 tested, the security-domain secret could not be rotated or revoked and protected both existing and future synced passkeys. Replacing one RP credential, or creating replacements inside the same compromised security domain, is therefore not a complete recovery. Treat the sync domain as compromised, follow provider guidance and migrate affected accounts to an uncompromised credential store or security domain where supported.

These are implementation attacks, not a failure of WebAuthn's signature design. The WebAuthn Level 3 specification defines the relying party's checks over authenticator data. Google's user verification guidance makes the operational distinction plain: preferred allows an assertion with UV false, while required should fail when user verification is unavailable, and the server must check that the returned UV flag is true.

A separate line of research reaches the same boundary from the browser side. Scott Helme's analysis of a 1Password WebAuthn wrapper found that an extension could broker a passkey ceremony on a page where the site's Permissions Policy had disabled passkey creation or authentication. That work required attacker-controlled page JavaScript, such as an XSS or compromised dependency, and 1Password treated the report as outside its vulnerability boundary. The useful defender lesson is narrower: browser policy, extension mediation, authenticator behaviour and server validation are separate enforcement points. A green sign-in result says little about which of them held.

Passkeys remain a better choice than phishable passwords. The mistake is treating the word passkey in an identity log as proof that the device owner unlocked a trusted authenticator. Defenders need the facts from the ceremony.

Why it matters to cloud defenders

A successful passkey assertion often sits one step before a high-value cloud session. The relying party may be an identity provider that federates into AWS, Azure or GCP. It may be the SaaS administration console itself. If the relying party accepts an assertion after a trust downgrade, downstream cloud logs can record a valid principal using a valid token. Whether they preserve the upstream WebAuthn flags or a usable transaction identifier is provider-specific. Verify each export schema rather than assuming that UV is present or absent.

This creates a split evidence problem. Endpoint telemetry can show a non-browser process reading Chrome's passkey sync database, touching passkey device state or accessing Chrome memory. It cannot prove which relying party later accepted an assertion. The relying party can retain the requested userVerification value and returned authenticator flags, but export coverage varies by implementation. Cloud audit logs start later, after federation or token issuance, and can see legitimate API calls without proving the upstream ceremony.

The practical exposure is wider than Google Workspace. A compromised workstation used by an administrator may hold passkeys for a source-code host, payroll platform, cloud console or identity provider. A recovered security-domain secret can expose the separate RP-scoped private keys synced for several relying parties; one passkey private key remains scoped to its own relying party. Unit 42's research deliberately withheld the names of most tested services, so defenders should not turn this into a vendor blacklist. The control belongs at every relying party they operate and at each identity junction they monitor.

This also changes incident scoping. Revoking one SaaS session does not answer whether synced passkey material was copied, whether a replacement UV key was enrolled or whether other relying parties accepted the same device. Password reset playbooks are especially weak here because there may be no password involved. The response boundary must include passkey registrations, device enrolment state, federated sessions and the endpoint that held the synced credential store.

ATT&CK mapping

The Silver path's attacker-controlled UV-key registration maps to T1556.006, Modify Authentication Process: Multi-Factor Authentication. The attacker invalidates the device's existing UV key and registers one they control, changing what the cloud authenticator trusts. Later assertions look valid because the verification factor itself changed. The basic UV-false path is different: it exploits a pre-existing relying-party validation defect and is not T1556.006 unless telemetry shows the actor changed authentication policy, code or an enrolled factor.

The credential-store access maps to T1555.003, Credentials from Password Stores: Credentials from Web Browsers. Unit 42 observed malware reading Chrome's local sync database and passkey_enclave_state, then reading Chrome process memory during recovery to obtain the security-domain secret. T1555.003 is more precise than calling wrapped key material an unsecured plaintext credential because ATT&CK explicitly covers browser credential files and browser process memory. Preserve the file, process and memory evidence separately so the mapping does not hide how the material was obtained.

T1556.006 is a better fit for the later trust change than calling every passkey event credential theft. Unit 42 describes several mechanisms. Reading credential metadata is discovery, recovering browser-held key material is credential access, and substituting a UV key changes authentication. The detector should preserve those distinctions because the required response differs. A UV mismatch calls for a relying-party code fix and session review. A new UV key without expected onboarding calls for device and account recovery. Extraction of the security-domain secret compromises the wider Google Password Manager security domain tested by Unit 42, not just one session or one RP credential.

The cloud payoff maps to T1078.004, Valid Accounts: Cloud Accounts when the accepted assertion results in access to an identity provider or cloud account. This is a second event, not a synonym for T1556.006. A defender should only assign T1078.004 after there is evidence of a cloud identity being used, such as a federated AWS console session, an Azure sign-in or GCP activity under the affected principal.

The research assumes malware already executes as the endpoint user but does not disclose how that initial code execution occurred. Mapping the entry to phishing, exploitation or supply-chain compromise would invent a fact. Keep the endpoint foothold as a prerequisite in the case record unless separate telemetry proves its initial-access technique. The supported chain is therefore narrow and honest: endpoint compromise of unknown origin, browser credential-store access under T1555.003, the Silver trust change under T1556.006, then valid cloud-account use under T1078.004. The basic UV-false path omits T1556.006 unless separate evidence proves an authentication change.

Detection guidance

Start by logging the WebAuthn ceremony at the relying party. Store one event after validation, before issuing a session. PasskeyCeremony should contain a unique CeremonyId, canonical account ID, hashed credential ID, relying-party ID, operation, requested user-verification policy, returned UP and UV flags, backup eligibility and state flags, signature-counter result, source network context and validation outcome. Include an enterprise DeviceId only when the RP or identity provider can bind it to endpoint inventory. Include FederationTransactionId only when the identity flow deliberately propagates a SAML, OIDC or provider transaction identifier into the downstream audit plane. Do not relabel two unrelated product session IDs as the same field. Hash the credential ID rather than writing the raw identifier into a broadly accessible log. Treat signCount as context: WebAuthn permits an authenticator that does not implement a counter to return zero, and synchronised credentials should not be classified from that field alone.

Do not derive uv_returned from the application's policy. Parse it from the signed authenticator data. The useful mismatch is user_verification_requested == "required" with uv_returned == false. That event should never produce a successful session. Alert even if application code rejects it, since repeated attempts can identify a compromised endpoint or a relying party being tested.

A second signal covers lifecycle changes, but the telemetry boundaries must stay separate. At the RP, record passkey registration, removal and replacement. A new RP credential followed by removal of the previous credential is useful account-takeover evidence, but it does not directly detect Unit 42's Silver path. Silver changes Google Password Manager's internal device UV key while existing RP credentials can continue to authenticate with UV true. Detect that path from provider device-onboarding telemetry when it exists, or from endpoint evidence such as unexpected deletion and recreation of passkey_enclave_state. Normalise a provider event as PasskeyProviderLifecycle with ProviderEvidenceId, canonical account ID, inventory-backed DeviceId, EventType and ExpectedChange; use device_uv_key_replaced only when the provider actually reports that change. ExpectedChange is local enrichment from an approved onboarding or recovery record, not a vendor field. Where neither provider nor endpoint source exists, record the Silver path as a blind spot rather than manufacturing an unexpected_device_reenrolment field in the RP ceremony.

On managed Windows endpoints, normalise those observations into PasskeyEndpointRisk with EndpointEvidenceId, canonical account ID, inventory-backed DeviceId, process identity and a controlled EndpointRiskReason. Useful values include browser_credential_store_access, browser_memory_access and passkey_device_state_reset. Unit 42 names Chrome's Sync Data\LevelDB area, passkey_enclave_state and Chrome process memory as investigation anchors, not universal signatures. Ordinary Sysmon telemetry can cover process access and file creation or deletion, but not arbitrary file reads. File-read detection needs an EDR source or targeted Object Access auditing such as Windows event 4663 with an appropriate SACL. Browser versions and profiles change, so validate the paths and event coverage in your estate.

The first KQL-style query catches the server-side invariant breach without depending on a product-specific schema. It derives CeremonyRiskReason from fields that actually exist in PasskeyCeremony:

Code block KUSTO
PasskeyCeremony
| where Operation == "authentication"
| where UserVerificationRequested == "required"
| where UserVerified == false
| extend CeremonyRiskReason = "uv_required_but_absent"
| project TimeGenerated, CeremonyId, AccountId, DeviceId,
          RelyingPartyId, CredentialIdHash, FederationTransactionId,
          SourceIp, ValidationOutcome, CeremonyRiskReason

A high-confidence correlation requires all three normalised planes. CloudIdentitySession must carry the deliberately propagated FederationTransactionId; PasskeyEndpointRisk and PasskeyCeremony must share an inventory-backed device and canonical account binding. The query excludes events missing those joins, requires endpoint evidence before the ceremony, and returns only the first linked cloud session. Thirty minutes before the ceremony and fifteen minutes after it are starting values to test, not universal constants. Do not fall back to IP-only joins, since corporate proxies and mobile networks make them noisy.

Code block KUSTO
let EndpointRisk = PasskeyEndpointRisk
| where EndpointRiskReason in
    ("browser_credential_store_access", "browser_memory_access",
     "passkey_device_state_reset")
| where isnotempty(AccountId) and isnotempty(DeviceId)
| project EndpointTime=TimeGenerated, AccountId, DeviceId,
          EndpointRiskReason, EndpointEvidenceId;
let CeremonyRisk = PasskeyCeremony
| where Operation == "authentication"
| where UserVerificationRequested == "required" and UserVerified == false
| where isnotempty(AccountId) and isnotempty(DeviceId)
| where isnotempty(FederationTransactionId)
| extend CeremonyRiskReason = "uv_required_but_absent"
| project CeremonyTime=TimeGenerated, CeremonyId, AccountId, DeviceId,
          FederationTransactionId, CeremonyRiskReason,
          RelyingPartyId, CredentialIdHash;
let CloudUse = CloudIdentitySession
| where Result == "success"
| where isnotempty(FederationTransactionId)
| project CloudTime=TimeGenerated, CloudAccountId=AccountId,
          FederationTransactionId, CloudSessionId,
          CloudProvider, TargetService, SourceIp;
EndpointRisk
| join kind=inner CeremonyRisk on AccountId, DeviceId
| where EndpointTime between (CeremonyTime - 30m .. CeremonyTime)
| join kind=inner CloudUse on FederationTransactionId
| where CloudAccountId == AccountId
| where CloudTime between (CeremonyTime .. CeremonyTime + 15m)
| summarize arg_min(CloudTime, *) by CeremonyId
| project EndpointTime, CeremonyTime, CloudTime, AccountId, DeviceId,
          EndpointRiskReason, CeremonyRiskReason, RelyingPartyId,
          CloudProvider, TargetService, CloudSessionId, SourceIp

Silver needs a separate lifecycle correlation because its assertion can carry UV true. The next query accepts either an unexpected provider-reported UV-key replacement or an endpoint device-state reset, then requires a successful UV-true ceremony and its first linked cloud session. A provider event is high-confidence evidence of the trust change. An endpoint reset is medium-confidence supporting evidence and must be tuned against legitimate recovery. The 30-minute lifecycle-to-ceremony window is only a near-immediate-use starting point. Silver creates reusable trust that can be exercised later, including when the victim device is offline. Keep an unresolved provider lifecycle finding open until the UV key or device is remediated, and test a longer estate-specific hunt window for delayed use.

Code block KUSTO
let LifecycleRisk = union
    (PasskeyProviderLifecycle
    | where EventType == "device_uv_key_replaced" and ExpectedChange == false
    | where isnotempty(AccountId) and isnotempty(DeviceId)
    | extend LifecycleRiskReason = "unexpected_provider_uv_key_replacement",
             RiskConfidence = "high"
    | project LifecycleTime=TimeGenerated, AccountId, DeviceId,
              LifecycleRiskReason, RiskConfidence,
              LifecycleEvidenceId=ProviderEvidenceId),
    (PasskeyEndpointRisk
    | where EndpointRiskReason == "passkey_device_state_reset"
    | where isnotempty(AccountId) and isnotempty(DeviceId)
    | extend LifecycleRiskReason = "endpoint_passkey_device_state_reset",
             RiskConfidence = "medium"
    | project LifecycleTime=TimeGenerated, AccountId, DeviceId,
              LifecycleRiskReason, RiskConfidence,
              LifecycleEvidenceId=EndpointEvidenceId);
let VerifiedCeremony = PasskeyCeremony
| where Operation == "authentication" and UserVerified == true
| where ValidationOutcome == "success"
| where isnotempty(AccountId) and isnotempty(DeviceId)
| where isnotempty(FederationTransactionId)
| project CeremonyTime=TimeGenerated, CeremonyId, AccountId, DeviceId,
          FederationTransactionId, RelyingPartyId, CredentialIdHash;
let CloudUse = CloudIdentitySession
| where Result == "success" and isnotempty(FederationTransactionId)
| project CloudTime=TimeGenerated, CloudAccountId=AccountId,
          FederationTransactionId, CloudSessionId,
          CloudProvider, TargetService, SourceIp;
LifecycleRisk
| join kind=inner VerifiedCeremony on AccountId, DeviceId
| where CeremonyTime between (LifecycleTime .. LifecycleTime + 30m)
| join kind=inner CloudUse on FederationTransactionId
| where CloudAccountId == AccountId
| where CloudTime between (CeremonyTime .. CeremonyTime + 15m)
| summarize arg_min(CloudTime, *) by CeremonyId
| project LifecycleTime, CeremonyTime, CloudTime, AccountId, DeviceId,
          LifecycleRiskReason, RiskConfidence, RelyingPartyId,
          CloudProvider, TargetService, CloudSessionId, SourceIp

If any cross-plane identifier is absent, emit a lower-confidence endpoint-only, lifecycle-only or ceremony-only finding and state which link is missing. Do not silently promote temporal proximity into causality.

If the identity provider cannot export WebAuthn flags, that absence is a detection finding of its own. Test the sign-in path with a development credential and confirm whether the audit event preserves requested UV, returned UV and a transaction identifier that survives into the downstream provider. A generic authenticationMethod=passkey field is not enough. It proves the credential type, not user verification or device trust.

Tune endpoint alerts against browser updates, enterprise profile migration and legitimate recovery. Chrome may recreate state after an approved reset. A password manager or EDR sensor may inspect browser processes. Close those cases only when the account-side sequence matches the change: known support ticket, expected device, successful recovery challenge and no unexpected federated session. A bare allowlist for the process name throws away the cross-plane evidence.

What to do now

  1. Review every relying party your organisation operates. Confirm that userVerification: "required" is paired with a server-side check of the signed UV flag before session issuance. Add a unit test that submits a valid assertion with UV false and expects rejection.

  2. Add ceremony telemetry before changing alert logic. Persist requested and returned verification state, a hashed credential identifier, a unique ceremony ID and a deliberately propagated federation transaction ID. Maintain an explicit device/account crosswalk where endpoint correlation is required. Restrict access because authentication logs can expose sensitive account and device relationships.

  3. Inventory identity providers and SaaS platforms that accept passkeys. Ask whether their export logs expose UV, RP credential lifecycle, provider device re-enrolment and a downstream correlation identifier. Where the platform hides those facts, record the specific blind spot. Endpoint plus downstream-session timing is supporting evidence, not a substitute for a missing transaction link.

  4. Hunt managed Windows endpoints for the sequence described by Unit 42: unusual access to Chrome passkey sync data, passkey device-state deletion or recreation, and browser-memory access. Confirm that the EDR or targeted audit policy actually records reads, process access and file lifecycle events before relying on the rule. Correlate through device, account and federation identifiers rather than IP address alone.

  5. Update account-takeover response. Isolate the compromised endpoint and preserve volatile evidence where appropriate. From a clean device, revoke active sessions, review and remove unfamiliar passkeys, and inspect every relying party represented in the synced credential metadata. If security-domain-secret extraction is plausible, do not present ordinary replacement inside the same Google Password Manager security domain as sufficient: Unit 42 reports that the tested secret could not be rotated or revoked and also protected future passkeys. Follow provider recovery guidance or migrate to an uncompromised credential store or security domain where supported.

  6. Keep passkeys enabled. The research concerns implementation and recovery boundaries, while phishing-resistant public-key authentication still removes the shared secrets attackers routinely steal. The right response is to validate the signed flags, watch trust changes and make the first downstream cloud session part of the same detection case.

01 ATT&CK references