Full Report
NEAR is a blockchain with a unique runtime and architecture from EVM chains. The network is broken into shards of validators to support lots of transactions on the network. This uniqueness is what drew the authors to this program. Upon initial analysis of the codebase, the receipt processing looked sketchy. The error handling appeared extremely complex yet solid at first glance. Eventually, they noticed a new change: max_receipt_size. To me, this is interesting - small changes can create subtle new invariants that were not there before. The validation of the receipt size was done in multiple locations. Notably, this only happened on the in take. In some scenarios, the receipt size could be increased during execution. In particular, if a receipt points to another receipt and the data from this other receipt is added to the original receipt, the actual size increases without validation. Having a receipt barely below the size limit and having it expanded causes some havoc. When being processed again as an incoming_receipt by other nodes, the exceeded size limit leads to a panic being hit. From their report, they were hunting for possible panics in the codebase and how to hit them. Aka, sink-to-source bug hunting. The impact is that all nodes receiving the receipt immediately crash. Some nodes would likely bounce back via watchdog programs but would then crash again. Once this receipt is dropped, the contract could be called again to trigger this crash over and over again though. The solution is somewhat interesting: the function validate_receipt actually removes the validation of the receipt size. In particular, they ONLY want to check for size constraints during creation and not expansion. I would have expected a check to be added on the expansion code to not exceed the limit, so this patch surprised me. The auditors were not thrilled with their payout. It was rated as a high severity issue, which has a range of 20K-200K. A similar vulnerability was paid out 150K. They were paid out less than half, so likely something between 80K-100K for the vulnerability, which is still great money. The authors claimed that they never talked directly with NEAR themselves - they only talked with HackenProof who talked to NEAR for them. From my perspective, programs are going to pay out what they want to pay out. When the previous vulnerability was reported, maybe NEAR was doing better financially; there's more to deciding a payout than just the impact of the vulnerability, especially when funds are not directly at risk. Immunefi does have a different business model that does seem to push for higher payouts though. I appreciate the insight into the HackenProof experience though. Overall, a fun bug! Sink to source bug hunting works well and the addition of the max size of the receipt introduced a funny invariant. Searching for No's and ways to trigger them is a great way to find DoS bugs.
Analysis Summary
# Vulnerability: NEAR Protocol Receipt Size Validation Denial of Service
## CVE Details
- **CVE ID**: Not specified (Common in private bug bounty reports)
- **CVSS Score**: Not provided (Internal rating: **High**)
- **CWE**: CWE-20 (Improper Input Validation) / CWE-617 (Reachable Assertion/Panic)
## Affected Systems
- **Products**: NEAR Protocol Blockchain
- **Versions**: Versions following the introduction of the `max_receipt_size` invariant.
- **Configurations**: Nodes participating in shard validation and receipt processing.
## Vulnerability Description
The vulnerability stems from an inconsistent application of receipt size limits. NEAR introduced a `max_receipt_size` check to prevent resource exhaustion; however, this validation was only enforced during the initial intake of a receipt.
During execution, certain operations allow a receipt to reference and incorporate data from another receipt. This expansion process increased the actual size of the receipt beyond the `max_receipt_size` limit without triggering a re-validation. When this oversized receipt was subsequently passed to other nodes as an `incoming_receipt`, the validation logic encountered the unexpected size, leading to a code "panic" (crash). Because the blockchain must process these receipts to reach consensus, nodes would repeatedly crash upon rebooting and attempting to process the same malicious receipt.
## Exploitation
- **Status**: PoC available (demonstrated to vendor via HackenProof)
- **Complexity**: Medium
- **Attack Vector**: Network (Smart Contract execution)
## Impact
- **Confidentiality**: None
- **Integrity**: None
- **Availability**: **High** (Total node failure/Persistent Denial of Service. The chain or specific shards could be halted by repeatedly triggering the crash via a contract).
## Remediation
### Patches
- The vendor updated the `validate_receipt` function. Interestingly, rather than adding checks to the expansion logic, the fix involved removing the rigid size validation during the `incoming_receipt` phase. The protocol now prioritizes enforcing size constraints during the **creation** phase rather than the **expansion/processing** phase to prevent panics during cross-node communication.
### Workarounds
- No manual workarounds provided; node operators must update to the latest patched version of the NEAR core client.
## Detection
- **Indicators of compromise**: Node logs showing "panic" errors related to `incoming_receipt` size validation or `max_receipt_size` exceeding limits.
- **Detection methods**: Monitoring for repeated node restarts (crash-looping) triggered by specific transaction receipts.
## References
- **Vendor advisories**: NEAR Foundation (via HackenProof)
- **Relevant links**:
- hxxps[://]hackenproof[.]com/
- hxxps[://]near[.]org/