Transaction tampering through a DEX front-end
Web3
A decentralised exchange asked us to test the web layer around its contracts. Their concern was precise: the smart contracts were audited, but the interface users actually trust to build a transaction was not.
Web & API penetration test, Decentralized exchange, severity CRITICAL, reported 2025
At a glance
- Challenge. The front-end rendered community-contributed token metadata as trusted markup, so a token description could run code where users build transactions.
- Approach. Using a test token we created, we traced metadata from source to render and showed injected code could alter a transaction before it reached the wallet.
- Result. Metadata renders as sanitised text, a content security policy and transaction preview limit any new path, and rendering and signing were retested.
- Impact. Anyone able to contribute token metadata could have run code in viewers' browsers and changed what a user approved in their wallet, without touching the audited contracts.
- Classification. CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'), OWASP Top 10 (2021): A03 Injection. Component: Token metadata rendering in the exchange front-end.
The challenge
The front-end displayed community-contributed token metadata, and it rendered part of that metadata as trusted markup so it could carry basic formatting. Metadata is attacker-controllable input. Rendering it as markup means a token’s description can carry code that runs in the browser of anyone who views it.
An audited contract does not help here, because the attack never touches the contract’s logic. It sits between the user’s intent and the transaction the wallet is asked to sign. The interface is the bridge where a human decision becomes an on-chain instruction, and if that bridge can be made to run untrusted code, the instruction the user approves is no longer the one they intended. A perfectly correct contract will faithfully execute a request the user was tricked into authorising.
This is a Web2 flaw with Web3 consequences, and it is missed precisely because the security attention went to the contract, where the assets appear to live, rather than to the interface, where the decisions are actually made.
Our approach
We tested the front-end as the untrusted boundary it is, focusing on every place external data reached the page as something other than plain text.
- Trace community-supplied metadata from its source to the point it was rendered
- Confirm whether that data was treated as markup or as text, and what a description could therefore carry
- Establish whether injected code could observe or alter a transaction before it reached the wallet
- Check whether a content policy constrained what injected code could do even if it ran
Delivered against a controlled test token we created, so the finding was reproducible without exposing any real user or asset.
From finding to fix
- Traced community-supplied token metadata
- Found it rendered as trusted markup
- Showed a wallet transaction could be altered
- Sanitized the rendering, retested
The outcome
Untrusted metadata is now rendered as text through a sanitising renderer rather than as trusted markup, a content security policy constrains what any injected code could do, and a transaction-preview step shows the user the permissions a signature actually grants before they approve it. The first change removes the injection; the second and third limit the damage if a new path is ever found.
We retested the rendering path and the signing flow after the fix. Reported as CRITICAL in 2025. Retest included in the engagement.
Check your own system
- Trace every piece of third-party or community-supplied data to where it is rendered and confirm it reaches the page as text, not markup.
- Replace any raw HTML rendering of user-supplied fields with an allow-list sanitiser, and test it with a payload in a token you control.
- Set a content security policy on the pages that build or sign transactions so injected script cannot load or send data to other origins.
- Show the user a decoded preview of what a signature grants, such as the spender and allowance, before the wallet prompt appears.
Read more case studies, see Web Application Penetration Testing, or tell us about your system on the contact page.