How Signed Updates Work

written by William Patton on July 21, 2026 in Security with no comments

Most WordPress plugins sold outside the official repository update themselves the same way: your site checks an online store for a new version, downloads a zip file, and swaps it in for the old plugin folder.

That works fine until the store itself gets compromised. If an attacker gets into the account that manages releases, they can swap in a malicious zip, and every site running that plugin will happily install it.

As far as the update mechanism is concerned, the store is the trust. Supply-chain attacks and store compromises are likely to get more common, and they’re what signed updates are built to stop.

GravityKit was one of the first WordPress plugin shops to add real signature verification, so a compromised store alone isn’t enough to push a malicious update into sites. Verification happens somewhere the attacker can’t touch.

The three parts of a signed update

A signed update system is really three separate jobs, done by three separate systems:

  1. The build system builds the zip and signs it
  2. The distribution system is the store, which just hands the zip and its signature to your site
  3. The receiver is your plugin’s own code, which checks the signature before it lets the new zip anywhere near your site

The trust no longer lives in the store. It lives in the build system, at the moment the zip is signed. That signature is public; anyone can check it later, not just your site.

The interesting part is the seams

The three pieces above are each simple on their own. Almost every real problem, and every real design decision, shows up in how they connect.

The keys

Signing uses a key pair: a private key that only the plugin author holds, and a public key that anyone can have. The private key signs the zip; the public key checks that signature.

If you have the public key and a signature checks out, you know the zip was signed by whoever holds the matching private key. No need to trust the store in between. The plugin itself holds a copy of the public key in its source code. That’s how it can verify the signatures.

What if the private key itself gets stolen? A stolen key can sign a new, malicious release just as validly as the real owner could. To help detect that, a public append-only log like Rekor can be used. Every signature gets recorded the moment it’s created.

A signature nobody logged, or a sudden new signature that shows up out of step with the real release history, is detectable.

Building and signing

Say version 2.4.0 of a plugin is ready to ship. The build system packages it into a zip, then signs that exact zip immediately in the same CI run, before it goes anywhere near the store. Signing is a step in the pipeline, not a separate manual task someone can forget.

Distributing the package

The store’s only job now is to hand your site two things: the zip, and its signature. It doesn’t need to be trusted to build anything correct. It’s just delivery. Anyone can get the zip and signature and verify it by hand, independent of whether they trust the store.

Verifying — and the ratchet

On your site, the plugin verifies the incoming zip against its signature and the public key before installing anything. If it doesn’t match, the update gets refused.

There’s a second check that some software shippers use: the ratchet. The software remembers the highest version it’s ever verified and installed, and refuses to accept anything older than that. Even if that older version is validly signed.

Without this, an attacker who gets hold of an old, legitimately signed zip (say, a version with a known vulnerability) could push it as an “update” and downgrade you straight into that hole.

What this actually buys you

Signed updates take the store out of the trust equation. You’re no longer trusting “this store account hasn’t been compromised”. You’re checking a cryptographic proof that ties the zip back to whoever built it.

What this doesn’t secure

Signing narrows down what you have to trust, it doesn’t remove the need to trust anything.

A signature only proves “the holder of this private key produced this exact file”. Not that the file is bug-free.

It doesn’t stop every path onto your site. Signing secures the update mechanism it’s wired into, not every way a file can end up in your plugins folder.

It doesn’t prevent someone from compromising the build system. Revoking a compromised key and getting every site off it is separate machinery, not something signing gives you for free.

It doesn’t force your site to keep checking for newer updates. Signing only protects an update that actually happens. An attacker who can quietly stop your site from ever checking for new versions leaves you sitting on an old, correctly-signed release forever, no invalid signature involved, because nothing new ever gets offered.

And the ratcheting only protects against a compromised store, not a fully compromised site.

None of that makes signing pointless; it just means it closes one specific door (a compromised store handing out bad files) and leaves the others exactly where they were before.