Skip to content

Transaction tampering through a DEX front-end

Transaction tampering through a DEX front-end

Transaction tampering through a DEX front-end

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.

Client

Decentralized exchange

Industry

Web3

Service

Web & API penetration test

Severity

CRITICAL

A dark envelope whose wax seal was lifted and pressed back, the seam lit in blue

01

The challenge

The challenge

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.

02

The approach

The approach

The 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.

03

The path

The path

The path

01

Traced community-supplied token metadata

02

Found it rendered as trusted markup

03

Showed a wallet transaction could be altered

04

Sanitized the rendering, retested

A fountain pen above a dark document with a different sheet beneath, outlined in blue

04

The outcome

The outcome

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.

CRITICAL

CRITICAL

Severity

Severity

2025

2025

Disclosed

Disclosed

Included

Included

Retest

Retest