Migration applicable to already migrated storage account
Description
migrate_from_0_1_0 allows the top_authority to migrate the storage account from the older StorageV010 model to the new Storage data model. This resizes the account, migrates the trusted_signers, and sets the treasury based on a value passed in by the top_authority. The migration requires a few conditions to be true, but one of the most important bits is that the anchor signature is equivalent to the Storage account's signature. Notably, this means that the migration does not change the anchor signature, because the name of the type for the account has not changed.
As the preliminary checks that allow the migration to go forward are true both before and after the migration, nothing prevents the top_authority from rerunning the migration again.
Impact
The top_authority could reset the treasury and/or putting the trusted_signers in a potentially corrupted state. This could be done by causing the num_trusted_signers to be set to an invalid value, breaking the signature validation logic.
Recommendations
As Anchor's discriminant is primarily dependant on the name of the type of the account, we recommend changing the name of the account from Storage to a a distinct name such as StorageV2. The migration step would validate that the account had a discriminant expected for Storage, but would eventually write StorageV2's discriminant to the account. This would prevent subsequent migrations as the discriminant of the account would change.
Remediation
This issue has been acknowledged by Pyth Data Association, and a fix was implemented in PR #2250↗.
The PR added a check requiring the size of the Storage account to match the size of the legacy layout. Since the legacy and new layouts differ in size, this prevents the migration from being performed more than once.
Pyth Data Association subsequently removed the migration feature entirely in commit .