Mine9

The Delegate Who Would Not Die: A Forensic Autopsy of XRPL's XLS-75 Permission Delegation Amendment

AnsemTiger
People

Hook

I want to begin with a specific sequence of events, because the sequence itself is the vulnerability.

An account on the XRP Ledger delegates a narrow permission to a second account. The second account uses it. Later, the delegator decides to revoke that permission โ€” the standard remedy that separates a "narrow grant" from an outright handover of control. The delegator submits the revocation. The ledger accepts it. And the permission survives.

Not because the revocation transaction reverted. Not because of a mempool race, not because of a stale fee, not because a validator dropped the transaction and the delegate replayed it. The permission survived because the second account deleted itself and recreated itself, and in doing so the binding between an account's identity and the authority it carried was severed in the wrong direction. The delegator revoked rights against an object that no longer pointed at the thing they believed they owned. The delegate walked through the hole, re-formed on the other side, and kept the keys.

Forensic autopsy of a digital economic collapse usually happens after the bodies are counted. This one is different. This one was stopped on the autopsy table. The flaw was found โ€” reportedly through a bug bounty rather than a design review โ€” while XLS-75, the XRPL Standards proposal that introduces Account Permission Delegation, was still in devnet. Version 1.0 was withdrawn before any mainnet vote. Version 1.1 arrived carrying a patch list that reads less like a bug fix and more like a confession about the maturity of the original design.

That is the event I want to dissect. Not the headlines โ€” there are, honestly, barely any โ€” but the code, the governance, and the uncomfortable question of what it means when a protocol discovers, in the final hour, that it was about to ship a revocation mechanism that could be quietly undone by the very party it was designed to restrain.


Context: The Machinery of a Silent Upgrade

To understand why one deleted-and-recreated account matters, you have to understand what XLS-75 actually is and where it sits inside the XRP Ledger's architecture.

The Delegate Who Would Not Die: A Forensic Autopsy of XRPL's XLS-75 Permission Delegation Amendment

Permission Delegation is an account-layer primitive. In plain terms, it lets Account A grant Account B a narrow, specific permission to act on A's behalf โ€” for example, to sign a particular class of transaction โ€” without ever handing B the keys or full control of A. This is the "vendor invoice in my name" model rather than the "power of attorney over my estate" model. It is, structurally, the same idea that the Cosmos ecosystem formalized years ago as Authz, and that Ethereum chased through ERC-4337 and the various session-key schemes layered on top of it. XRPL is not inventing a new paradigm here. It is porting a proven one โ€” the persistent complaint about account abstraction on any chain is never "does the concept work" but "does it handle the edges."

And the edges on XRPL are unusually sharp, because Permission Delegation is not a standalone feature. It is a connector. The proposal documentation explicitly couples it to a cluster of other XRPL DeFi modules that were waiting on it: Vault, Lending, Batch, and Confidential MPT. Read that list again. Vault is custody logic. Lending is credit logic that consumes custody logic. Batch is multi-operation atomicity. Confidential MPT is a privacy-preserving token standard that has to interact with authority checks. Permission Delegation is the hinge under all of them.

This is why a flaw inside XLS-75 is not a flaw inside one feature. It is a load-bearing wall. If delegation is compromised, every module that assumes "authority can be reliably granted and reliably withdrawn" inherits the compromise. In a bear market, where the question on every reader's mind is not "how do I make 40x" but "is my collateral still mine," a broken revocation mechanism is the most dangerous possible failure mode. Withdrawal is the security primitive that underwrites everything else. If withdrawal can be silently defeated, nothing above it is trustworthy.

Now, the timeline deserves a flag before I go further, because I am a forensic auditor and I do not let bad data slide simply because it is inconvenient. The source material places the introduction of XLS-75 at 2025 and then, bizarrely, places a re-support event at June 2026 โ€” a date that cannot coexist with the rest of the sequence without assuming a time machine is part of the amendment process. I am treating that date as a data error until an official governance record proves otherwise. It does not change the technical analysis, but it does tell you something about how casually even protocol-critical timelines get transcribed. Verify the record, not the narrative.

The governance track itself is the part that redeems the story. XRPL amendments do not ship by developer fiat. They must pass through a validator vote โ€” the Unique Node List consensus โ€” before activation. Between devnet validation and mainnet activation sits a gauntlet: a bug bounty program, a completed QA report, external audit, and, as of this cycle, a third-party public dashboard built by an independent developer to track how thoroughly each amendment has been exercised on the test network. That dashboard exists because the community grew tired of asking "is this thing actually tested?" and getting vibes in return.

So the setting is this: a genuinely important infrastructure primitive, a known and validated paradigm being ported onto a chain whose DeFi ambitions depend on it, wedged inside a governance machine that โ€” at least this time โ€” did what it was supposed to do. And at the center of it, a design-level flaw that the machine caught at the last possible clean moment.


Core: The Flaw at the Seam of Identity and Permission

Let me get precise, because the imprecision here is where the danger hides.

An XRP Ledger account is identified by an address. That address is derived from a key, and it is persistent in the ordinary sense โ€” the address is the name. But an account on XRPL is not immortal. It can be deleted. Specifically, an account can be removed from the ledger when it is emptied and meets the network's conditions for removal, and โ€” crucially โ€” the same address can later be recreated by funding it again with the original key. The name persists even when the object briefly does not.

Permission Delegation V1.0 stored delegated authority in a way that associated permissions with that name. The delegator's revocation logic targeted the name. The delegate's ability to hold the permission also traveled with the name. Put those two facts together and you get the exploit: the delegate deletes the account, the permissions tied to the name are not cleanly torn down, the delegate recreates the account at the same address, and the authority re-attaches to the resurrected account. The delegator's revocation โ€” submitted in good faith against what they believed was "Account B" โ€” has nothing to bite on, because the object they revoked against had, for a moment, ceased to exist and then returned wearing the same face.

This is not a missing require. This is not a reentrancy lock that someone forgot to set. This is a design-level defect: the binding between an account's identity and its persistent authority was never made atomic with respect to the account's lifecycle. I have written before that the most expensive bugs are never in the arithmetic โ€” they are in the assumptions. Here the assumption was "an account address denotes a continuous subject that can hold and lose authority." Delete-and-recreate breaks the continuity while preserving the label. The label was trusted. The continuity was not checked.

Here is why this is worse than a typical implementation bug, and why it earns the word design-level. Implementation bugs live inside a function that does the wrong thing. Design bugs live in the space between functions โ€” in the contract between contracts, in the shared understanding of two subsystems that never actually met to negotiate. The delegation authority subsystem and the account lifecycle subsystem each behaved correctly in isolation. The vulnerability was in their conjoined assumption. You cannot find that by fuzzing a single entrypoint. You find it by asking, "what are the two things this code assumes are true at the same time, and can I make one of them false without the other noticing?" That is exactly the style of analysis I ran against the 0x Protocol v2 contracts years ago โ€” manually, line by line, on the EIP-20 proxy patterns, because automated tools kept missing the exchange-logic reentrancy vectors that only appear when you trace how one layer's guarantee becomes another layer's precondition. This flaw belongs to the same family.

Now scale the impact. Permission Delegation is built for exactly the users Akinyele named when presenting the feature โ€” "users and custodians." Custodians are the entire point. A custodial arrangement is a delegation of authority under a regulatory expectation of revocability: the client can terminate the mandate, and the custodian's power must end. The V1.0 flaw is, at its core, a mechanism by which a delegated party can make the delegator's revocation unenforceable โ€” by exploiting the account lifecycle rather than the permission logic. If that had shipped to mainnet, the damage ceiling is not "one clever user loses funds." The damage ceiling is the full authority the delegate held, retained indefinitely against the delegator's explicit instruction to revoke.

I have said this before about the LUNA/UST collapse and I will say it again here in a different key: the bug was not in the code, it was in the economic and structural assumptions the code was built to serve. In 2022, the failure was an algorithmic peg that lacked circular stability โ€” a design that could not survive the reflexivity of its own users. Here, the failure was an authority model that lacked lifecycle stability โ€” a design that could not survive the reflexivity of an account that is also a name. Different decade, same lesson: audit the design, not just the diff.


Core: `isDelegable` and the Arithmetic of Trust

The second technical item is quieter, and I suspect it will be underweighted precisely because it is quieter. It was classified as medium severity, and the researchers behind its disclosure framed it carefully: absent malicious delegator behavior, there is no substantive impact.

I want to translate that sentence, because in security work, that sentence is a promise, not a proof.

The issue is an integer overflow in the isDelegable field or function โ€” the piece of logic that determines whether a given transaction type can be delegated at all. XRPL, like most ledger codebases, is written with unsigned integer types in many places because most quantities in a ledger are non-negative: balances, reserves, sequence numbers, counts. Unsigned arithmetic has a characteristic failure mode โ€” underflow near zero produces a value that wraps around to the maximum of the type, and overflow near the ceiling wraps to the minimum. When that arithmetic feeds a check, the wrap can flip a predicate from "denied" to "allowed" or the reverse. The classic exploit shape is: make a value that should be small become enormous (or vice versa) at the exact moment a comparison decides whether you are permitted to do something.

The disclosure notes that the overflow here is not exploitable to gain authority unless the delegator is malicious. That is a meaningful qualifier โ€” and it is exactly the kind of qualifier I treat as a loaded gun on the mantelpiece. "No impact without a malicious delegator" does not mean "no impact." It means the attack requires the consent โ€” or the malice โ€” of the account owner. In a custody context, the delegator is often not a trusting individual but a platform operator. If the platform operator is the adversary, the qualifier evaporates. The threat model in real deployments is not "honest delegator, honest delegate." It is "one of the two is trying to take the other's assets." So a medium-severity classification that rests on "no malicious delegator" is a medium-severity classification that has assumed away the exact actor who matters.

There is a second reason to care about the overflow beyond its immediate exploitability. Its mere presence tells you something about the maturity of the type-checking and serialization layer underneath the whole amendment. Overflow bugs are rarely isolated. They cluster. Where you find one unchecked unsigned arithmetic path feeding a predicate, you should assume there are neighbors that have not yet been exercised โ€” because the underlying discipline of "every arithmetic path that touches a security check must be bounded and proven" was not uniformly applied. I have made this argument at the code-review level for years: an integer overflow is never just an integer overflow. It is a signal about the rigor of the layer it lives in. The reason people fix the one you found and then run a full audit of the arithmetic surface is not paranoia. It is pattern recognition.

Decoding the silent language of smart contracts, the isDelegable flag is meant to be a bright line: this transaction type may or may not be delegated, full stop. Bright lines built on unbounded arithmetic are not bright lines. They are lines that cast shadows you cannot see until the light shifts.


Core: What V1.1 Actually Repairs

The most honest document in this whole episode is not the audit report. It is the V1.1 fix list. Read it as a confession and it tells you exactly how immature V1.0 was.

The list, as reported, includes: handling the delegate's identity edge cases (the delete-and-recreate class of problems), blocking unintended delegation interactions with Vault and Lending, correcting reserve accounting, closing multi-signature bypass paths, and tightening the behavior of revocation itself. That is not a patch list. That is a structural rework of the amendment's threat surface, and every item on it is a different category of failure.

Start with the fact that Vault and Lending delegation had to be explicitly blocked. This is the connector problem made visible. Permission Delegation was supposed to be the hinge for Vault and Lending โ€” the primitive they would lean on. But in V1.0, the delegation model apparently allowed "unintended" interactions with those modules โ€” meaning an authority grant could produce an effect in custody or credit logic that nobody designed for and nobody tested. When your feature's own dependent modules have to be walled off from it pending a redesign, that is a design that was shipped ahead of its integration model. The interface contracts between delegation and DeFi modules did not exist with enough precision to be safe.

Then reserve accounting. XRPL charges reserves for ledger objects โ€” accounts and certain data structures require a locked minimum of XRP. Delegation creates persistent objects (permission entries), and persistent objects have reserve implications. A flawed reserve model is not a cosmetic bug; it is an economic bug. Under-charging opens spam and griefing vectors where an attacker creates permission objects cheaply and bloats the ledger. Over-charging silently taxes legitimate users. Either direction is a real defect, and the fact that reserve accounting needed correcting at all tells you the object-lifecycle economics of delegation were not fully modeled when V1.0 was proposed.

Then multi-signature bypass paths. This one should stop anyone cold. XRPL accounts can be controlled by multi-signature โ€” multiple keys must jointly sign, and there are structures that restrict which keys may sign which transaction types, precisely so that one key cannot unilaterally move funds. If Permission Delegation offers a path around multi-sig restrictions โ€” a way to grant and then exercise an authority that the multi-sig policy intended to forbid โ€” then delegation becomes a silent override of the account's own security policy. The account owner thinks they configured multi-sig to require two of three keys for a withdrawal. An attacker with one delegated permission walks around the entire arrangement. "Closing the bypass path" is the fix-list phrase. The weight it carries is: delegation, in V1.0, could defeat the account's own stated protection.

And finally, revocation tightening. This is where I separate the flaw from the family of flaws. The delete-and-recreate bug is the famous one. But the fix list treats revocation as a general area needing hardening, not a single-line change. That implies the original revoke semantics had multiple weak points, not one โ€” an inconsistent model of what a revocation does and what it is guaranteed to defeat. A revocation mechanism is only as strong as its worst edge case, because an attacker only needs the one edge. If your revoke guarantee has three holes, you have zero guarantee, and you have three separate bodies of code each believing the property is someone else's job.

This is the pattern I keep returning to across a career of post-mortems: the danger is never the bug you found; it is the proof you assumed you had. V1.0 was withdrawn, not patched in place. My read is that XRPL amendments cannot be edited once proposed โ€” they must be superseded and re-proposed. That is a governance constraint with real cost: it means a flawed design does not get fixed, it gets replaced, and the replacement restarts the clock. The gap between withdrawing V1.0 and shipping a testable V1.1 is not idle time. It is the price of not catching the design flaw a phase earlier.


Core: The Test Distribution Problem

Numbers are the most seductive form of false comfort in security work, so I want to handle the test figures with a scalpel.

The QA report for V1.1 discloses roughly a hundred-plus functional tests against the amendment, and somewhere around nineteen cross-functional tests. The instinct โ€” especially in a community eager for reassurance โ€” is to read "5088 items tested" and exhale. I read the ratio.

Functional tests validate the feature in isolation: does delegation work, does revocation work, does the permission entry form correctly, do the documented behaviors hold. Cross-functional tests validate the seams โ€” and it is at the seams that V1.0 died. The delete-and-recreate flaw lived at the seam between delegation and the account lifecycle. The unintended Vault/Lending interactions lived at the seam between delegation and the DeFi modules. The multi-sig bypass lived at the seam between delegation and the account's security policy. Every single defect that sank V1.0 was a seam defect.

So the number that matters is not the functional count. It is whether the seam coverage is proportionate to the number and complexity of the seams. Delegation interacts with, by the documentation's own admission: the multi-sig system, Vault, Lending, Batch, Confidential MPT, and the account lifecycle. That is at minimum six interfaces, each of which can fail in both directions. Nineteen cross-functional tests against that integration graph is thin โ€” not negligently thin, but thin enough that I would not call it proven. A conservative reading is that the cross-functional suite covers the known seams that the V1.0 post-mortem surfaced, plus a handful of neighbors. It almost certainly does not cover the seams nobody has thought about yet, because that is the nature of the unknown.

There is a specific number I keep watch for in reports like this: the ratio of happy-path seam tests to adversarial seam tests. Functional suites are full of happy paths. Seam adversarial tests โ€” where you deliberately drive one subsystem's edge state into another subsystem's assumption โ€” are the expensive ones and the ones most often skipped. The V1.0 flaw was an adversarial seam test that nobody wrote until a bounty hunter effectively wrote it for them. I would want to see the V1.1 suite prove that specific class of test now exists by construction, not by accident.

The Delegate Who Would Not Die: A Forensic Autopsy of XRPL's XLS-75 Permission Delegation Amendment

The honest auditor's conclusion here is not "V1.1 is unsafe." It is: V1.1 has closed the specific seams that wounded V1.0, and the evidence that it has generalized the discipline to unknown seams is weaker than the headline test count suggests. That is a caveat, not a verdict โ€” and it is exactly the caveat you carry into post-activation monitoring rather than into a decision to ship or not ship.


Contrarian: The Blind Spot Nobody Audits

Now I pull the thread that the standard reading of this story will not pull, because the standard reading is a comfortable one: "bounty program worked, team responded, flaw fixed before mainnet, everything is fine."

I do not object to that reading. I object to how it obscures the thing that should actually worry us.

Silence in the code speaks louder than audits โ€” and the loudest silence in this whole episode is the manner in which the V1.0 flaw was found. It was, by the account I am working from, surfaced through a bug bounty. Not through the design review that should have preceded the bounty. The bounty is a net. It catches what swims into it. The design review is a filter. It is supposed to catch what should never have entered the water. When a category of defect โ€” the account-lifecycle binding โ€” has to be caught by the net rather than the filter, it means the filter is not looking for that category. And if the filter was not looking for account-lifecycle defects in the previous amendment cycle, the question you must ask is: what other categories is the filter not looking for, right now, in the current one?

This is the structural blind spot that no audit contract covers. Cantina audited the code. The bounty program incentivized whitehats to attack the code. The QA report tested the code. Every one of those instruments operates on the artifact โ€” the artifact that was written subject to whatever assumptions the designers held. You cannot audit your way out of a design assumption that all your auditors share. The delete-and-recreate flaw is invisible to anyone who, like the original designers, treats the account address as a continuous subject. It only becomes visible when someone refuses that assumption โ€” which is exactly what a bounty hunter optimizes for and exactly what a scoped audit rarely does. I have watched this exact dynamic in the AI-agent trading protocol work: the reward-distribution logic favored synthetic volume over genuine participation, and no amount of testing the distribution function in isolation would reveal it, because the function did precisely what it was written to do โ€” it optimized for the metric that the design told it to optimize, and the design was wrong. The bug was in the objective, and the objective was invisible to the auditors because they, like the designers, had accepted it.

There is a second blind spot, and it is governance rather than code. XRPL's amendment process centralizes decision weight in the Unique Node List โ€” the validator set each node trusts. The promise of an on-chain vote is a promise of broad validation, but the actual validator distribution matters enormously. A flaw that survives all the devnet testing reaches mainnet only if the vote passes, and the vote passes based on validators who trust the QA and audit artifacts they are shown. The security of the amendment and the decentralization of its approval are two different properties, and a thin, concentrated validator set weakens the second even when the first holds. I am not asserting UNL is dangerously concentrated. I am asserting that the community's claim "the amendment process is safe because validators vote" quietly borrows credibility from a decentralization claim that deserves its own separate, skeptical audit. The two are not the same sentence, and they get spoken as if they were.

And the third blind spot is the one the disclosure language hands you directly: "no substantive impact absent a malicious delegator." I flagged this in the arithmetic section; I flag it again at the system level, because it is a pattern across the whole fix list, not a one-off. Every mitigation that reduces severity by assuming a benign actor is a mitigation that moves the residual risk onto the threat model you don't control. In a permission-delegation system designed for custodians, the benign-actor assumption is precisely the assumption that the custody use case violates. The product's own customers are the adversarial case. When your risk statement and your target market contradict each other, the risk statement is the lie you are telling yourself.

Where logic meets the fragility of human trust โ€” this is that place. The code can be made to satisfy every spec the designers wrote and still be unsafe, because its safety depends on a designer: a human who chose how to bind identity to authority, who chose which seams to test, who chose to write "no impact unless malicious" and moved on. That human choice is the real attack surface. And it is the one surface this entire episode demonstrates nobody audited.


Takeaway: What Survives the Audit

So what do I actually take from this, standing at the end of the dissection with the ledger still running and the amendment still un-activated?

The XRP Ledger community got a gift it may not recognize as a gift. It learned โ€” cheaply, on devnet, with no mainnet vote cast โ€” that its account abstraction primitive had a design-level hole at the exact seam that matters most for the exact use case the primitive is built to serve. It learned that its bug bounty program works and that its amendment governance has a functioning withdrawal path. That is a real positive. But the gift is only a gift if the community treats the lesson as a lesson, and that requires asking the uncomfortable question rather than the comfortable one. The comfortable question is "is V1.1 safe?" The uncomfortable question is "why does a project this mature keep catching design-level, not implementation-level, defects โ€” and through the net rather than the filter?"

I audit code for a living. I have spent weeks manually tracing proxy patterns to find what automated tools miss, and reverse-engineering tick math to find where liquidity models break, and digging through collapsed stablecoins to find where reflexivity eats the peg. The single most consistent finding across all of that work is this: the defect that makes it to mainnet is almost never the defect that was hardest to see. It is the defect that everyone agreed was not there. The delete-and-recreate flaw was not hard to see once you questioned the assumption. It was hard to see because the assumption was shared by everyone who looked.

For the reader with assets exposed to XRPL DeFi โ€” the Vault user, the Lending borrower, the custodian client โ€” the read is not "panic" and it is not "all clear." The read is that the primitive that will gate the safety of your gold-plated, institution-flavored custody is still being written, still being discovered, and still relying on a bounty net to catch the category of flaw its design review cannot yet name. Watch the activation vote, not the press release. Watch the cross-functional surface when Vault and Lending finally lean on this hinge. And when the next amendment arrives with a clean audit and a green QA report, ask the question the report cannot answer: whose assumption did the auditors share with the designers, and what is hiding inside it.

The architecture of freedom, compiled in bytes, has a compile-time dependency on the humility of the people who write it. That dependency is the one thing a validator vote cannot confirm, an audit cannot certify, and a bounty cannot guarantee. It is, and always will be, the only part of the system that has to be verified the hard way โ€” one honest post-mortem at a time.

Market Prices

Coin Price 24h
BTC Bitcoin
$78,064 -1.63%
ETH Ethereum
$2,471.5 -1.32%
SOL Solana
$100.97 -3.02%
BNB BNB Chain
$716.9 -5.23%
XRP XRP Ledger
$1.38 -3.47%
DOGE Dogecoin
$0.0851 -6.15%
ADA Cardano
$0.2130 -3.05%
AVAX Avalanche
$7.75 -2.88%
DOT Polkadot
$1.1 -7.23%
LINK Chainlink
$11.79 -4.95%

Fear & Greed

69

Greed

Market Sentiment

Event Calendar

{{ๅนดไปฝ}}
10
05
upgrade Ethereum Pectra Upgrade

Raises validator limit and account abstraction

08
04
upgrade Solana Firedancer

Independent validator client goes live on mainnet

30
04
upgrade Celestia Mainnet Upgrade

Improves data availability sampling efficiency

28
03
unlock Arbitrum Token Unlock

92 million ARB released

18
03
unlock Sui Token Unlock

Team and early investor shares released

15
04
halving Bitcoin Halving

Block reward reduced to 3.125 BTC

22
03
unlock Optimism Unlock

Circulating supply increases by about 2%

12
05
halving BCH Halving

Block reward halving event

๐Ÿงฎ Tools

All โ†’

Altseason Index

41

Bitcoin Season

BTC Dominance Altseason

Gas Tracker

Ethereum 28 Gwei
BNB Chain 3 Gwei
Polygon 42 Gwei
Arbitrum 0.5 Gwei
Optimism 0.3 Gwei

Market Cap

All โ†’
# Coin Price
1
Bitcoin BTC
$78,064
1
Ethereum ETH
$2,471.5
1
Solana SOL
$100.97
1
BNB Chain BNB
$716.9
1
XRP Ledger XRP
$1.38
1
Dogecoin DOGE
$0.0851
1
Cardano ADA
$0.2130
1
Avalanche AVAX
$7.75
1
Polkadot DOT
$1.1
1
Chainlink LINK
$11.79

๐Ÿ‹ Whale Tracker

๐Ÿ”ต
0xf700...bf99
30m ago
Stake
1,778,500 DOGE
๐Ÿ”ด
0xc178...3e64
6h ago
Out
2,140,008 USDT
๐Ÿ”ด
0x852f...edf7
12h ago
Out
4,469.29 BTC

๐Ÿ’ก Smart Money

0x778d...fdad
Experienced On-chain Trader
+$4.2M
77%
0xb3fe...882b
Early Investor
+$4.1M
68%
0x0eed...05ac
Market Maker
+$2.2M
89%