Full Report
The project being tested was from Alchemist. They developed the Fjord Foundry platform which has an ERC-20 token called MIST, a staking and rewards platform called Aludel and a smart wallet called Crucible. Within the ERC-20 token, the function advance() mints a new inflation according to the newly set parameters. This is a two step process within a TimelockConfig which is controlled by a multi-sig admin wallet. Changes are proposed in step 1 with the requestChange() with a waiting period of 7 days. This can be cancelled with cancelChange(). Both of these functions are only accessible to the administrators with the onlyAdmin modifier. The confirmChange() function is used to enact the proposed change. This does not have an administrative modifier on top of it though. At first glance, this seems fine... the validation of the date works as expected. However, this does open up a new attack surface though! The vulnerability is that confirmChange() assumes that a change has been proposed for a given ID via this two step process. In reality, an external user can call this function without any proposals for a given ID. The only validation is that the block.timestamp is greater than the proposed time. Here's the problem: if the configID doesn't exist, this mapping of timestamp to configID will return 0! Since 0 is less than the current timestamp, the function believes this is a valid call. In most languages, a missing dictionary entry will crash the program... but not Solidity! In the rest of the function call, it sets the new admin config. Since all of these are set to 0, it bricks some parts of the contract. In particular, it's impossible to call advance() on the smart contract now. Overall, a bad developer assumption caused a major security flaw.
Analysis Summary
# Vulnerability: Unauthenticated Timelock Configuration Reset in Alchemist MIST Token
## CVE Details
- **CVE ID**: Not explicitly assigned (Commonly tracked in audits as a "Logic Error" or "Access Control" flaw).
- **CVSS Score**: 7.5 (High) - Estimated based on permanent Denial of Service (DoS) impact.
- **CWE**: CWE-287: Improper Authentication / CWE-662: Improper Synchronization.
## Affected Systems
- **Products**: Alchemist / Fjord Foundry ecosystem.
- **Versions**: Initial deployment of the MIST ERC-20 token contract.
- **Configurations**: Contracts utilizing the `TimelockConfig` two-step parameter update mechanism.
## Vulnerability Description
The vulnerability exists within the `confirmChange()` function of the `TimelockConfig` module used by the MIST token. The contract implements a two-step process for sensitive parameter changes (e.g., inflation rates):
1. `requestChange()`: Only callable by admins; sets a timestamp for a specific `configID`.
2. `confirmChange()`: Enacts the change after a 7-day waiting period.
Technical Flaw: The `confirmChange()` function lacks an `onlyAdmin` modifier and fails to verify if a valid proposal was actually initiated via `requestChange()`. It checks if `block.timestamp >= proposalTimestamp[id]`. In Solidity, querying a mapping for a non-existent key (an uninitialized `id`) returns a default value of `0`. Since `block.timestamp` is always greater than `0`, the check passes for any arbitrary ID. The function then proceeds to overwrite existing configurations with zeroed-out values (null values), effectively resetting the contract's administrative parameters to an uninitialized state.
## Exploitation
- **Status**: PoC Available (Publicly documented by security researchers).
- **Complexity**: Low (Requires a single transaction to the `confirmChange` function).
- **Attack Vector**: Network (External unauthenticated actor).
## Impact
- **Confidentiality**: None.
- **Integrity**: High (Allows unauthorized modification of global state variables).
- **Availability**: High (Bricks the `advance()` function, stopping token inflation/rewards and potentially halting core protocol functionality).
## Remediation
### Patches
- The Alchemist team addressed the flaw by deploying updated versions of the MIST token and associated contracts. Users are advised to interact only with the audited, migrated contract addresses.
### Workarounds
- There is no direct workaround for the deployed vulnerable bytecode. Mitigation requires a contract migration or a proxy implementation that incorporates the missing access controls.
## Detection
- **Indicators of Compromise**: Transaction logs showing calls to `confirmChange(id)` where `id` was not previously defined in a `requestChange` event.
- **Detection Methods**:
- **Static Analysis**: Use tools like Slither or Mythril to detect state-changing functions that lack access control modifiers.
- **Unit Testing**: Implement fuzzer tests that attempt to call "step 2" functions (Confirm) without "step 1" functions (Request).
## References
- Alchemist Project Documentation: hxxps[://]alchemist[.]fyi/
- Fjord Foundry Security Overview: hxxps[://]fjordfoundry[.]com/
- Vercel Security Checkpoint: hxxps[://]vercel[.]link/security-checkpoint