Prepared by:
HALBORN
Last Updated 06/27/2025
Date of Engagement: January 31st, 2025 - February 13th, 2025
100% of all REPORTED Findings have been addressed
All findings
5
Critical
2
High
0
Medium
0
Low
2
Informational
1
Ripple
engaged Halborn to conduct a security assessment on XRP Ledger (XRPL) feature amendments beginning on Jan 31, 2025 and ending on Feb 13, 2025, focusing on PR #5060. The feature introduces a new transaction type Batch that enables atomic execution of multiple transactions, supporting various modes of operation including all-or-nothing, only-one, until-failure, and independent execution patterns.
The team at Halborn
assigned a full-time security engineer to assess the security of the node. The security engineer is a blockchain and smart-contract security expert in advanced penetration testing, smart-contract hacking, and deep knowledge of multiple blockchain protocols.
The scope of this audit encompasses:
The new Batch transaction type and its fields
Multi-account transaction signing mechanisms
Inner transaction security controls
Fee calculation and processing
Transaction integrity and atomicity guarantees
Halborn performed a combination of manual review of the code and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of the Batch Transaction feature security assessment. The following phases and tools were used:
Research into the architecture, purpose, and use of the Batch Transaction feature through extensive documentation review.
Manual code review and walkthrough to identify potential logic issues in transaction processing and security controls.
Security control testing for signature verification, fee processing, and atomic execution guarantees.
Implementation verification of inner transaction controls and batch mode operations.
Trust model validation for both single-account and multi-account transaction scenarios.
Documentation analysis covering security considerations and implementation guidelines.
Functional testing of transaction processing flows and error handling mechanisms.
Edge case testing for complex transaction scenarios and failure modes.
Review of error handling and recovery mechanisms.
EXPLOITABILITY METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Attack Origin (AO) | Arbitrary (AO:A) Specific (AO:S) | 1 0.2 |
Attack Cost (AC) | Low (AC:L) Medium (AC:M) High (AC:H) | 1 0.67 0.33 |
Attack Complexity (AX) | Low (AX:L) Medium (AX:M) High (AX:H) | 1 0.67 0.33 |
IMPACT METRIC () | METRIC VALUE | NUMERICAL VALUE |
---|---|---|
Confidentiality (C) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Integrity (I) | None (I:N) Low (I:L) Medium (I:M) High (I:H) Critical (I:C) | 0 0.25 0.5 0.75 1 |
Availability (A) | None (A:N) Low (A:L) Medium (A:M) High (A:H) Critical (A:C) | 0 0.25 0.5 0.75 1 |
Deposit (D) | None (D:N) Low (D:L) Medium (D:M) High (D:H) Critical (D:C) | 0 0.25 0.5 0.75 1 |
Yield (Y) | None (Y:N) Low (Y:L) Medium (Y:M) High (Y:H) Critical (Y:C) | 0 0.25 0.5 0.75 1 |
SEVERITY COEFFICIENT () | COEFFICIENT VALUE | NUMERICAL VALUE |
---|---|---|
Reversibility () | None (R:N) Partial (R:P) Full (R:F) | 1 0.5 0.25 |
Scope () | Changed (S:C) Unchanged (S:U) | 1.25 1 |
Severity | Score Value Range |
---|---|
Critical | 9 - 10 |
High | 7 - 8.9 |
Medium | 4.5 - 6.9 |
Low | 2 - 4.4 |
Informational | 0 - 1.9 |
Critical
2
High
0
Medium
0
Low
2
Informational
1
Impact x Likelihood
HAL-01
HAL-02
HAL-03
HAL-04
HAL-05
Security analysis | Risk level | Remediation Date |
---|---|---|
Fee Manipulation in Batch Transaction | Critical | Solved |
Unbounded Resource Consumption in Fee Calculation | Critical | Solved - 03/10/2025 |
Missing sequence number enforcement in preflight | Low | Solved - 03/10/2025 |
Missing OnBehalfOf Transactions Check | Low | Future Release - 03/10/2025 |
Integer Overflow | Informational | Solved - 03/10/2025 |
//
The calculateBaseFee
The batch transaction processing function is vulnerable to integer overflow, potentially allowing attackers to bypass transaction fee requirements. There's also a missing check at the end of the function to ensure that the fees cannot be zero.
{
auto const seq = env.seq(alice);
env(batch::outer(alice, seq, ripple::STAmount(0), tfAllOrNothing),
batch::inner(pay(alice, bob, XRP(10)), seq + 1),
batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
batch::sig(bob),
ter(tesSUCCESS));
// Close ledger
env.close();
}
to simulate a successful attack chaining integer overflow issue and unbounded loop, add this line at the end of the Batch::calculateBaseFee
function
XRPAmount const TEST = XRPAmount{1};
return std::numeric_limits<std::uint64_t>::max() + TEST;
Always that Batch::calculateBaseFee
should never return zero to defend about such attack that could be introduced through unbounded loops or integer overflows.
SOLVED: The fee calculation is now improved, and the issue no longer exists
//
The calculateBaseFee
function contains two unbounded loops that process transaction arrays (sfRawTransactions
and sfBatchSigners
) without proper size validation. Since this function can be triggered through RPC calls before transaction validation or fee payment, an attacker could craft a transaction with extremely large arrays to cause denial of service through excessive CPU consumption.
{
auto const seq = env.seq(alice);
env(batch::outer(alice, seq, ripple::STAmount(30), tfAllOrNothing),
batch::inner(pay(alice, bob, XRP(10)), seq + 1),
batch::inner(pay(bob, alice, XRP(5)), env.seq(bob)),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
batch::sig(bob),
ter(tesSUCCESS));
// Close ledger
env.close();
}
Add Early Size Validation before the preflight.
SOLVED: The issue was solved, and fixes were introduced in isRawTransactionOkay
function and calculateBaseFee
as well.
//
The Batch::preflight()
function performs various validations on inner transactions but does not verify sequence numbers of the transactions. While sequence numbers are checked during the actual transaction application phase, performing this validation earlier in the preflight stage could prevent invalid transactions from proceeding further in the processing pipeline.
Add sequence number validation in the Batch::preflight()
function.
SOLVED: The issue is now solved by using unordered_set
to store sequence.
//
The specification document states that "OnBehalfOf will not be allowed on Batch transactions" (Section A.9), but there appears to be no explicit validation in the preflight checks to enforce this restriction.
The lack of validation creates a discrepancy between the intended security model and the actual implementation.
Add explicit validation in the preflight checks.
FUTURE RELEASE: The Ripple team will solve this finding in a future release.
//
The XRPAmount
class in include/xrpl/protocol/XRPAmount.h
implements various arithmetic operations for handling XRP amounts in drops (the smallest unit of XRP). The class uses std::int64_t
as its underlying type but performs arithmetic operations without overflow/underflow checks, which could lead to silent failures and incorrect balance/fee calculations.
Implement checked arithmetic operations that throw exceptions on overflow/underflow.
SOLVED: The Ripple team introduced a set of safe math functions safeAdd, safeSub, safeMul, safeNeg.
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
Ripple - Batch - Smart Contract Assessment
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed