NNS Update 2024-09-04 Cycles Minting Canister Security Hotfix

TL;DR

A security hotfix on the cycles minting canister (CMC) was applied a few hours ago. The source code is now published at commit 77f48ae6 and can be verified, which fixes 3 security issues.

Security Issue 1: minted cycles rate-limiting can be triggered by failed and refunded operations

For every case where CMC mints cycles, it first adds cycles to its own balance and then sends them to other canisters (cycles ledger or new canisters being created). In addition, there is rate-limiting for creating cycles. Before the fix, for any operation that needs X cycles, it mints X and adds to its balance, which means the rate limiting is applied to the same rate as the operations which need cycles, while the operations can still fail later.

Attack Scenario

For example, an attacker can periodically attempt to top-up a canister which doesn’t exist, and their ICP will get refunded later, while still contributing to the rate-limiting, hence preventing other users from minting cycles. An attacker only needs to send ICPs worth ~14T per second in order to prevent any cycle minting, and if the combination of top-up->refund operations take 5 seconds, then the attacker only needs ICPs worth 70T cycles in total, which they will eventually get back. This scenario is written as a test here.

Applied Fix

In order to fix this issue, now CMC only mints the amount of cycles in order to ensure the balance is at least what the operation needs (here). Effectively, the rate-limiting is now applied to the successful operations, as failed operations will not cause the cycles to leave the balance of CMC.

Security Issue 2: canister creation cycles might be lost

When the create_canister endpoint on the CMC is called, it first accepts the cycles, attempts to create the canister, and refunds the cycles back to the sender if creation fails. However, if the refund also fails, then the sender has no way of getting the cycles back.

Attack Scenario

To exploit this, an attacker can try to make those calls fail by filling up the message queues involved for the 2 canister creation and refund calls (e.g. by making top up calls with small amounts).

Applied Fix

To fix this, now the cycles are only accepted after the canister is successfully created, and if the creation fails, the cycles are simply not accepted.

Security Issue 3: deposit memo in NotifyMintCyclesArg can be arbitrarily long

When the notify_mint_cylces endpoint on the CMC is called, it will validate the request and send the cycles to the cycles ledger. However, currently CMC does not validate the deposit_memo field, while the cycles ledger validates that it should be no longer than 32 bytes.

Attack Scenario

An attacker can intentionally send notify_mint_cycles requests with large deposit_memo (e.g. close to the 2 MiB message limit) and therefore slow down the message processing between the subnets that the CMC and cycles ledger are in.

Applied Fix

The fix is very simple - also validates the deposit_memo length in the CMC before calling the cycles ledger.

Note: we have not observed any evidence to indicate that any of those vulnerabilities have been exploited.

Also, kudos to @mraszyk who found those issues and suggested the fixes, and @msumme for coming up with the fix for issue 2 and its implementation.

3 Likes

Any idea why we are having a lot of failed transactions? Which have been said to be in issues with minting cycles. Is this anyhow related to it? x.com