Safeguard
Application Security•

CWE-1291 Reusing One Public Key for Debug and Production Code

If debug and production firmware verify against the same key, a leaked debug image runs on shipped devices. How CWE-1291 happens and a simple check to catch it.

Safeguard Security Team
5 min read

CWE-1291 is short to state and costly to ignore: the same public key is used for signing both debug and production code.

This belongs to firmware, bootloader and secure boot work, but the lesson applies to any signing setup. Signing is only worth something when the key tells you what kind of code you are looking at.

How it happens

Public-key cryptography is commonly used to verify the integrity and authenticity of another entity. A typical case is firmware. A company that wants its firmware to run only on its own hardware can have the device decrypt an encrypted hash of the firmware image using a public key, and compare it to the hash it computes from the image itself. The public key becomes the root of trust. MITRE points out that this means the key must be protected and used properly.

During development, debug firmware turns on many hardware debug hooks, debug modes and debug messages. These facilities give extra views into the firmware's capability and, in some cases, extra capability inside the chip or SoC. If they are compromised, an attacker could take full control of the system.

Now the reuse problem. Once the product leaves manufacturing and enters production, MITRE says it is good practice to use a different public key. Debug firmware images are known to leak. If the debug key is also the production key, a leaked debug image is accepted on a production device. All the internal debug capabilities then open to the attacker.

With separate keys, the same leak is far less damaging. The attacker holds a debug image the production device refuses to run. MITRE says the damage is then limited to the intellectual property in that image, and the production machines stay closed.

In short, one key turns "debug builds leak sometimes" into "every shipped device can be opened".

What an attacker gains

MITRE rates the likelihood of exploit as high and lists a wide range of consequences: reading memory, modifying memory, executing unauthorized code or commands, and gaining privileges or assuming identity. It lists loss of confidentiality, integrity, availability, access control, accountability, authentication, authorization and non-repudiation, and the impact varies by context.

That breadth is what you would expect when the attacker can run code with the full debug capability of the device.

How to find it

MITRE gives two detection methods, both rated high effectiveness: an architecture or design review, and dynamic analysis with manual results interpretation. Both reduce to one check. Compare the debug key with the production key and make sure they are not the same.

You can make that concrete. If both keys are available as public key files, compare their fingerprints:

openssl pkey -pubin -in debug_key.pub -outform DER | openssl dgst -sha256
openssl pkey -pubin -in prod_key.pub  -outform DER | openssl dgst -sha256

If the two digests match, the keys are the same. Put this in a release check so a mix up fails the build instead of reaching manufacturing.

Also look at what the device itself trusts. The key that matters is the one embedded in the device, in ROM or fuses. Extract it from a production unit and compare it with the key used to sign your debug builds, not only with a key file in a repository.

Beyond that:

  • Confirm the production signing key is held in a different place, with different access, than the debug key.
  • Confirm the debug key can be retired or revoked, without needing to touch production.
  • Check that artifacts built for debug are labeled and stored separately from production artifacts.

How to fix it

MITRE's mitigation, for the implementation phase, is one line: use different keys for production and debug.

Make that operational:

  1. Generate separate key pairs for debug and production, and record which is which.
  2. Embed only the production public key in shipped devices. Keep the debug public key for development units.
  3. Add a pre-release check that fails when the two public keys match.
  4. Restrict access to the production private key more tightly than the debug one, since the debug one is expected to be used often.
  5. Plan for a leak. Assume a debug image will get out and make sure it does not run on production hardware.

Try it yourself

Provenance and attestation are how teams prove which key and which build produced an artifact. The demo shows the idea for software artifacts, and the same reasoning applies to firmware images.

Click through it at your own pace, or open it full screen.

Quick check

Why is a leaked debug image so dangerous when the key is shared?

The production device accepts anything signed with the shared key, so the leaked debug image runs there with all its debug capabilities open.

What is the one check MITRE recommends?

Compare the debug key with the production key and make sure they are not the same.

What is the benefit of separate keys if a debug image still leaks?

The image will not run on production machines, so damage is limited to the intellectual property in that image.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.