{"record":{"id":"841c8a82e4d6ae22","repo":"dotnet/maui","slug":"cert-certificatethumbprint-exists-in-localmachin","errorCode":null,"errorMessage":"Cert {certificateThumbprint} exists in LocalMachine\\TrustedPeople but its private key is not accessible from this non-elevated process, and removing the stale cert also requires elevation. Please remove the stale entries manually and re-run this task elevated once:\n  Remove-Item Cert:\\LocalMachine\\TrustedPeople\\{certificateThumbprint}\n  Remove-Item Cert:\\CurrentUser\\My\\{certificateThumbprint}","messagePattern":"Cert (.+?) exists in LocalMachine\\\\TrustedPeople but its private key is not accessible from this non-elevated process, and removing the stale cert also requires elevation\\. Please remove the stale entries manually and re-run this task elevated once:\n  Remove-Item Cert:\\\\LocalMachine\\\\TrustedPeople\\\\(.+?)\n  Remove-Item Cert:\\\\CurrentUser\\\\My\\\\(.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"eng/devices/windows.cake","lineNumber":101,"sourceCode":"\tlocalTrustedPeopleStore.Close();\n\n\t// If a cert exists, verify it has a usable user-scoped private key in CurrentUser\\My. A cert\n\t// installed by an older version of this script may reference a private key in the machine key\n\t// container (C:\\ProgramData\\Microsoft\\Crypto\\...), which is unreadable from a non-elevated\n\t// process — signtool would then fail mid-build with an opaque \"No certificates were found that\n\t// met all the given criteria\". If unusable, remove the stale entries and fall through to the\n\t// creation path below.\n\tif (!string.IsNullOrEmpty(certificateThumbprint) && !IsCurrentUserSigningCertUsable(certificateThumbprint))\n\t{\n\t\tInformation(\"Existing cert {0} has no usable user-scoped private key; removing and recreating.\", certificateThumbprint);\n\t\ttry\n\t\t{\n\t\t\tRemoveCertByThumbprint(StoreLocation.LocalMachine, \"TrustedPeople\", certificateThumbprint);\n\t\t\tRemoveCertByThumbprint(StoreLocation.CurrentUser, \"My\", certificateThumbprint);\n\t\t}\n\t\tcatch (System.Security.Cryptography.CryptographicException ex)\n\t\t{\n\t\t\tthrow new Exception(\n\t\t\t\t\"Cert \" + certificateThumbprint + \" exists in LocalMachine\\\\TrustedPeople but its private key \" +\n\t\t\t\t\"is not accessible from this non-elevated process, and removing the stale cert also requires \" +\n\t\t\t\t\"elevation. Please remove the stale entries manually and re-run this task elevated once:\\n\" +\n\t\t\t\t\"  Remove-Item Cert:\\\\LocalMachine\\\\TrustedPeople\\\\\" + certificateThumbprint + \"\\n\" +\n\t\t\t\t\"  Remove-Item Cert:\\\\CurrentUser\\\\My\\\\\" + certificateThumbprint,\n\t\t\t\tex);\n\t\t}\n\t\tcertificateThumbprint = null;\n\t}\n\n\tif (string.IsNullOrEmpty(certificateThumbprint))\n\t{\n\t\tInformation(\"Generating cert\");\n\t\tvar rsa = RSA.Create();\n\t\tvar req = new CertificateRequest(\"CN=\" + certCN, rsa, System.Security.Cryptography.HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);\n\n\t\treq.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection\n\t\t{","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/eng/devices/windows.cake#L83-L119","documentation":"Thrown in GenerateMsixCert when an existing cert (by thumbprint) is found in LocalMachine\\TrustedPeople but IsCurrentUserSigningCertUsable returns false (private key in an inaccessible machine key container), and the attempt to remove the stale cert from both LocalMachine\\TrustedPeople and CurrentUser\\My throws CryptographicException — because deleting from LocalMachine requires elevation that the current non-elevated process lacks. The message instructs manual removal with elevated PowerShell.","triggerScenarios":"A cert created by an older version of this script (which used MachineKeySet) is still in the stores; running the packaged test task non-elevated on a machine where that stale cert exists; the non-elevated process can read the store but cannot delete from LocalMachine.","commonSituations":"Upgrading the repo/scripts on a dev machine that previously ran an older cert-generation flow; shared CI runner where a prior job left a machine-container-keyed cert; switching from elevated to non-elevated runs after the cert was installed by an admin.","solutions":["Run the two Remove-Item commands from an elevated PowerShell exactly as the message specifies, then re-run the task (the creation path will make a user-keyed cert going forward).","Run the whole task elevated once; after the new user-keyed cert is created, subsequent non-elevated runs reuse it.","If you cannot elevate, use a different commonName (--commonname) so a fresh cert is created without touching the stale one.","After cleanup, verify with IsCurrentUserSigningCertUsable-style logic that the new cert's key is user-scoped before building the MSIX."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before the task, detect the stale-cert condition non-destructively\nvar existing = new X509Store(\"TrustedPeople\", StoreLocation.LocalMachine);\nexisting.Open(OpenFlags.ReadOnly);\nvar stale = existing.Certificates.Cast<X509Certificate2>()\n    .FirstOrDefault(c => c.Subject == \"CN=\" + certCN && !IsCurrentUserSigningCertUsable(c.Thumbprint));\nexisting.Close();\nif (stale != null)\n    Information($\"Stale cert {stale.Thumbprint} detected; an elevated run is needed to remove it.\");","typeGuard":null,"tryCatchPattern":"// The existing catch already wraps CryptographicException; surface a fix-it message and halt\ncatch (System.Security.Cryptography.CryptographicException ex)\n{\n    Error($\"Run elevated once to remove stale cert {certificateThumbprint}, then re-run non-elevated.\");\n    throw new Exception(\"Stale cert requires one-time elevation to remove.\", ex);\n}","preventionTips":["Run GenerateMsixCert elevated once after upgrading scripts so the new user-keyed cert replaces any machine-keyed one.","Avoid deleting the cert after first creation to prevent re-triggering the elevation requirement.","Use a distinct --commonname when you cannot elevate, to sidestep a stale cert."],"tags":["cake","windows","certificate","msix","elevation","x509"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}