CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-C32P-WCQJ-J677
9.00.04%

Tachyon: Hijacking Blockchain Time in CometBFT

Alon Barad
Alon Barad
Software Engineer

Feb 14, 2026·6 min read·22 visits

PoC Available

Executive Summary (TL;DR)

CometBFT's 'BFT Time' calculation failed to verify that timestamps came from active validators. An attacker can skew the block time forward, breaking smart contracts and vesting logic.

A critical consensus vulnerability in CometBFT allows malicious proposers to manipulate the blockchain's internal clock ('BFT Time') by injecting invalid signatures into block commits. This 'Tachyon' attack bypasses validator set verification during time calculation, enabling attackers to artificially advance block timestamps and potentially trigger premature vesting or disrupt time-sensitive smart contracts.

The Hook: Time is a Flat Circle (Until it Isn't)

In the world of distributed systems, 'time' is a messy hallucination we all agree to share. For blockchains built on the Cosmos stack, that hallucination is maintained by CometBFT (formerly Tendermint). It doesn't rely on NTP or a central atomic clock; instead, it uses a deterministic algorithm called BFT Time. This is supposed to be the bedrock of the chain—a weighted median of timestamps provided by validators in the previous block.

Why does this matter? Because everything in DeFi relies on it. Unbonding periods, vesting schedules, oracle updates, and governance timeouts all query this ctx.BlockTime(). If you control the clock, you don't just control the history; you control the future assets of the chain.

Enter GHSA-C32P-WCQJ-J677, alias 'Tachyon'. It turns out that the mechanism CometBFT used to calculate this median time was a little too trusting. It assumed that the data fed into the time calculation was strictly from the VIP list (the active validator set). It wasn't. This vulnerability is the equivalent of letting a random passerby yell the time into the room, and the blockchain deciding, 'Yeah, sounds about right.'

The Flaw: The Unverified Median

The core of the issue lies in how MedianTime is calculated. In CometBFT, the timestamp for Block $H$ is derived from the Precommit votes of Block $H-1$. The logic is sound in theory: take the weighted median of the timestamps from the validators who signed the previous block. This prevents a single malicious validator with 1% voting power from setting the time to the year 3000.

However, the implementation had a gaping logic error. The function responsible for calculating this median iterated through the signatures in the LastCommit structure, but it failed to strictly enforce membership checks against the active validator set during the calculation phase.

A malicious block proposer could craft a LastCommit that included signatures with valid structures but wild timestamps. Because MakeBlock (the block construction method) didn't force MedianTime to validate that every timestamp contributor was actually allowed to vote, the algorithm happily ingested these outliers. The math works perfectly—it calculates the median—but the input data is poisoned. It's a classic case of 'Garbage In, Garbage Out,' except the garbage is a timestamp set to unlock your vesting tokens three years early.

The Code: Silent Failures

Let's look at the smoking gun in state/state.go. The vulnerability stems from a lack of error propagation and validation context.

Before the Fix: The MedianTime function likely returned a time value without complaining, even if the input data was sketchy. The MakeBlock function would simply take this value and stamp it onto the new block.

After the Fix (Commit bf8274f): The developers introduced a hard stop. MedianTime now cross-references the signatures against state.LastValidators. If a signature claims to be from Index 5, the code checks if the address actually matches the validator at Index 5. Crucially, MakeBlock now handles errors returned by MedianTime.

Here is the diff that saves the ecosystem:

// state/state.go
 
func (state State) MakeBlock(...) (*types.Block, error) {
    // ... snip ...
    // The fix introduces error handling here
    ts, err := MedianTime(lastCommit, state.LastValidators)
    if err != nil {
        // Now we panic/error out instead of creating a broken block
        return nil, fmt.Errorf("error making block while calculating median time: %w", err)
    }
    timestamp = ts
    // ... snip ...
}

Furthermore, deep in types/validation.go, checks were added to ensure that commit.Signatures[i] corresponds strictly to the validator at that index. If the proposer tries to inject a 'ghost' signature to skew the time, the validation logic now throws a ErrInvalidCommitSignature.

The Exploit: Warp Speed Ahead

So, how do we weaponize this? You need to be a Validator with proposing rights (or have compromised one). The attack vector isn't about breaking cryptography; it's about abusing the state machine's logic.

The Attack Chain:

  1. Wait for your turn: The attacker waits until they are the designated Proposer for Height $H$.
  2. Forge the Past: The attacker constructs the LastCommit for the previous block. They collect real signatures from honest validators (to ensure the block passes validity checks), but they interleave or append crafted entries. These entries contain timestamps set far in the future.
  3. Bypass the Filter: Prior to the patch, the attacker inserts these high-timestamp entries. The MedianTime function includes them in the weighted list.
  4. Propose the Block: The attacker broadcasts the new block. Honest nodes receive it. If their local validation logic mirrors the flawed generation logic (which it often does in consensus engines), they accept the block as valid.
  5. Profit: The block is committed. The chain time jumps forward. Vesting contracts check block.timestamp, see that the 'future' has arrived, and release funds. The attacker unbonds instantly or triggers time-based arbitrage opportunities.

The Impact: Catastrophic Time Travel

The severity of this bug cannot be overstated for an application-specific blockchain. In standard web apps, a wrong clock might mess up your logs. In crypto, time is money.

  • Vesting Cliffs: Many Cosmos chains have massive token allocations locked in vesting contracts. A time jump could release millions of dollars of tokens onto the market years ahead of schedule.
  • Light Clients & IBC: The Inter-Blockchain Communication (IBC) protocol relies heavily on timeouts and proof validity periods. Skewed time could cause packets to timeout prematurely or, worse, trick light clients into accepting expired states.
  • Consensus Halt: If the time jump is too egregious, honest nodes running slightly different configurations or external monitoring tools might panic, causing a chain split or a halt. While a halt is better than a theft, it's still a DoS.

The fact that this was labeled 'Critical' and 'Catastrophic' by the maintainers suggests they found a working PoC that could reliably trigger these conditions in a live network.

The Fix: Trust, but Verify (Strictly)

The remediation is straightforward but essential: Validation must happen at the source.

The patch ensures that MedianTime is no longer a passive calculator. It acts as a gatekeeper. It explicitly verifies that every timestamp contributing to the median comes from a legitimate, active validator. If the Proposer tries to slip in a fake vote to skew the math, the function returns an error, the block creation fails, and the attack is neutralized.

Action Plan:

  1. Upgrade Immediately: Move to v0.37.18 or v0.38.21.
  2. Check Your Logs: Look for ErrInvalidCommitSignature or failures in MakeBlock. This could indicate someone tried to exploit this against your node.
  3. App-Level Defense: If you are a dApp developer, consider using block height rather than block time for critical logic where possible, as height is harder to manipulate in this specific manner.

Official Patches

CometBFTCometBFT v0.38.21 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
9.0/ 10
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:N/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

CometBFT (all versions < 0.37.18)CometBFT (0.38.x < 0.38.21)Cosmos SDK chains using vulnerable CometBFT versions

Affected Versions Detail

Product
Affected Versions
Fixed Version
CometBFT
CometBFT
< 0.37.180.37.18
CometBFT
CometBFT
0.38.0 - 0.38.200.38.21
AttributeDetail
CWECWE-665: Improper Initialization
Attack VectorNetwork (Consensus Layer)
CVSS9.0 (Critical)
ImpactConsensus Failure / Logic Manipulation
Componentsstate/state.go, types/validation.go
Fix Commitbf8274fcdbcab2bc652660ae627196a90a6efb97

MITRE ATT&CK Mapping

T1565.001Stored Data Manipulation
Impact
T1496Resource Hijacking (Time)
Impact
CWE-665
Improper Initialization

The product does not initialize or incorrectly initializes a resource, which may leave the resource in an unexpected state.

Vulnerability Timeline

Vulnerability Discovered
2026-01-01
Patch Released (v0.38.21)
2026-01-23
Advisory Published
2026-01-30

References & Sources

  • [1]GitHub Advisory GHSA-C32P-WCQJ-J677
  • [2]Patch Diff

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.