# #43217 \[BC-Insight] Incorrect public key notification after key rotation

**Submitted on Apr 3rd 2025 at 19:05:25 UTC by @Rhaydden for** [**Attackathon | Movement Labs**](https://immunefi.com/audit-competition/movement-labs-attackathon)

* **Report ID:** #43217
* **Report Type:** Blockchain/DLT
* **Report severity:** Insight
* **Target:** <https://github.com/immunefi-team/attackathon-movement/tree/main/util/signing/signing-admin>
* **Impacts:**
  * A bug in the respective layer 0/1/2 network code that results in unintended smart contract behavior with no concrete funds at direct risk

## Description

## Brief/Intro

The signing-admin CLI tool has a flaw in its key rotation. Afterr rotating a signing key in either AWS KMS or HashiCorp Vault, the app is notified with the public key of the *old* key instead of the newly rotated key. This happens because the key retrieves the public key before the rotation operation has actually taken place from the perspective of the `SignerBackend`.

## Vulnerability Details

In the `rotate_key` function in `rotate_key.rs`, the function's execution flow is as follows:

1. An `HttpApplication` instance is created for notification.
2. A `Backend` enum instance (representing the key storage backend) is created.
3. A `SignerBackend` enum instance (used to retrieve the public key) is created. This creation happens *before* the actual key rotation. The `SignerBackend` is initialized with the `canonical_string` which identifies the key to be rotated.

   ```rust
   let signer = match backend_name.as_str() {
       "vault" => {
           // ... Vault client creation ...
           SignerBackend::Vault(HashiCorpVault::<Ed25519>::new(
               client,
               canonical_string.clone(),
               "transit".to_string(),
           ))
       }
       "aws" => {
           // ... AWS client creation ...
           SignerBackend::Aws(AwsKms::<Secp256k1>::new(
               client,
               canonical_string.clone(),
           ))
       }
       _ => return Err(anyhow::anyhow!("Unsupported signer backend: {}", backend_name)),
   };
   ```
4. A `KeyManager` is created, which is responsible for performing the key rotation using the `Backend`.
5. The `key_manager.rotate_key()` function is called. This function interacts with either AWS KMS or HashiCorp Vault to rotate the key associated with the `canonical_string`.

   ```rust
   key_manager
       .rotate_key(&canonical_string)
       .await
       .context("Failed to rotate the key")?;
   ```
6. The `public_key()` method is called on the `signer` instance that was created in step 3. Since this instance was created *before* the rotation, it is still associated with the old key material.

   ```rust
   let public_key = signer
       .public_key()
       .await
       .context("Failed to fetch the public key from signer")?;
   ```
7. The `application.notify_public_key()` function is called with the `public_key` obtained in step 6, which is the public key of the *old* key.

   ```rust
   key_manager
       .application
       .notify_public_key(public_key)
       .await
       .context("Failed to notify the application with the public key")?;
   ```

As a result, applications will be configured to verify signatures with the wrong key.

## Impact Details

Apps relying on the key rotation notification mechanism will receive the incorrect public key. If the application uses the notified public key to verify signatures generated by the new key, the verification will fail because the notified public key corresponds to the old key. In scenarios where the public key is used for authentication purposes, the application will not be able to authenticate entities using the new key.

This falls under the category of "A bug in the respective layer 0/1/2 network code that results in unintended smart contract behavior with no concrete funds at direct risk" since it affects the signature verification without directly exposing funds to theft.

## References

<https://github.com/immunefi-team/attackathon-movement//blob/a2790c6ac17b7cf02a69aea172c2b38d2be8ce00/util/signing/signing-admin/src/cli/rotate\\_key.rs#L37-L106>

## Proof of Concept

1. Set up the signing-admin with either AWS KMS or HashiCorp Vault backend
2. Configure an application to receive public key updates
3. Run the key rotation command:

```rust
signing-admin rotate-key --canonical-string "my-key" --application-url "http://my-app/api" --backend "aws"
```

4. Verify that the application receives a public key
5. Inspect the AWS KMS or Vault to confirm that key rotation has occurred
6. Compare the public key sent to the application with the current public key in the backend
7. The keys will not match.

## Fix

Move the `SignerBackend` creation code to after the `key_manager.rotate_key()` call. This ensures that the signer is created with the new key, and applications are notified with the correct public key.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reports.immunefi.com/movement-labs-attackathon/43217-bc-insight-incorrect-public-key-notification-after-key-rotation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
