Keep the private key for a self-hosted extension off the web server, readable by as few people as possible, backed up in a secure place, and used only in a controlled release step. Chrome requires every update to be signed with the same key, so whoever holds it can ship code to your whole fleet.
Why this key matters so much
Chrome's documentation says that when you package an extension, Chrome creates a .crx file and a .pem file holding the private key, and warns: "Do not lose the private key!" It is needed to update the extension. The update docs add that each new package must be signed with the same private key as the installed version.
That gives the key two properties. If you lose it, you cannot publish updates to the installed copies. If someone steals it, they can sign a package that Chrome will accept as an update. Treat it like a code-signing key, because functionally it is one.
Where the key should live
| Location | Verdict |
|---|---|
| Next to the files on the update server | Avoid. A server compromise would hand over both |
| In the source repository | Avoid. Repository access is much wider than release access |
| In a secrets manager with audit logging | Good |
| On an offline machine or hardware-backed store | Better for high-risk extensions |
| Only on one developer's laptop | Avoid. Single point of loss |
Steps to set it up
- Generate once, on a trusted machine. Do not generate keys in a shared CI image you do not control.
- Store it in one controlled place. Limit read access to the release process and a small named group.
- Separate signing from building. Let the build produce an unsigned package and have a protected step sign it after review.
- Log every use. You should be able to answer who signed which version and when.
- Back it up. Keep an encrypted copy with a second custodian so a lost laptop is not a lost extension.
- Write a recovery plan. Decide in advance what you will do if the key leaks: block the old extension ID by policy and roll out a new one under a new key.
What a leak looks like
You may not see it directly. An attacker with the key still needs a way to deliver a package, for example by writing to your update server. So watch both ends: key access logs and changes on the update host. Compare the version number served with the version you expect, and alert when they differ.
If you suspect a leak, the policy tools described in how to respond to a malicious extension apply directly. Chrome's blocklist policy disables a blocked extension that is already installed and prevents the user from enabling it.
Try it yourself
Click through it at your own pace, or open it full screen.
Watch how a pull request is held until checks pass. A protected signing step should work the same way, only after review.
Quick check
Can I change the key later?
Chrome requires updates to match the key of the installed version, so a replacement key means installed copies cannot take updates signed with it. Plan the migration before you need it, and check Chrome's documentation for how the key relates to the extension ID.
Does a store-hosted extension have this problem?
The developer dashboard creates the package for you when you upload, so you do not hold a packaging key in the same way. Your risk shifts to the security of the publisher account.
Sources
Last reviewed: 19 October 2026.