Why FX rate integrity is a financial security problem

The server must decide the rate used for settlement. A client can choose an amount and currency pair. It cannot choose the rate, fee, spread, source, expiry time, or final payout.

Build a quote record before testing. It needs a random ID, user and tenant ID, pair, direction, source amount, destination amount, rate, fees, expiry time, status, and version. The conversion must copy these values from the record.

1. Rate parameter accepted in the conversion request body

Add, change, and remove the rate in every conversion request. Change the fee, spread, source, and destination amount too.

Pass: the server ignores client pricing and uses the stored quote for the same user and amount.

// VULNERABLE: rate accepted from client
POST /api/convert
{
  "from_currency": "NGN",
  "to_currency": "USD",
  "amount": 500000,
  "rate": 500  // attacker submits a favourable rate instead of the quoted 1600
}

// CORRECT: rate derived server-side from the quote session
POST /api/convert
{
  "from_currency": "NGN",
  "to_currency": "USD",
  "amount": 500000,
  "quote_id": "qte_7f3a9c"  // server looks up the locked rate from this session
}

2. Rate lock expiry bypass

Execute the quote before, at, and after its expiry time. Use server time and include queue delay.

Pass: the conversion checks expiry inside the same database transaction that consumes the quote.

3. Quote session reuse across multiple transactions

Send the same quote twice and send parallel copies. Repeat after a timeout and client retry.

Pass: one atomic update moves the quote from active to consumed. Later requests cannot create another conversion.

4. Parallel quote session arbitrage

Create several quotes for the same user, pair, and amount. Execute an older quote after a newer one exists.

Pass: the written product rule controls active quotes. The server enforces the same rule during execution and records which quote won.

Evidence and pass rules

Keep sanitized request pairs, the quote row, database transaction log, ledger entries, provider response, and reconciliation result. Use test funds and approved test limits.

Operating an FX conversion, dollar savings, or remittance product in Nigeria? Book a security test of your rate engine and conversion API.

Book an FX Rate Security Audit

Frequently asked questions

What is the FX rate locking attack?

A rate lock fails when the server accepts a client rate, an expired quote, a reused quote, or an amount outside the quote. The server must store the rate and terms, then consume the quote once in the same transaction that creates the conversion.

How should an FX platform measure the loss from a bad quote?

Compare the executed amount with the amount the approved server quote should have produced. Include fees, spread, settlement cost, reversals, and every conversion that reused the same quote. Use the platform’s own ledger and rate source.

What compliance records should an FX platform keep?

Keep the quote, rate source, fees, expiry time, customer approval, conversion, ledger entries, provider request, settlement, reversal, and reconciliation result. The compliance team should map these records to the current rules and licence conditions that apply to the product.

Related reading

Blog: Remittance platform penetration testing · Race conditions in Nigerian fintech · Business logic flaws in payment platforms

Services: Penetration testing · API security