feat: security audit fixes
This commit is contained in:
43
apps/api/src/lib/wallet-binding.ts
Normal file
43
apps/api/src/lib/wallet-binding.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* JWT ↔ wallet-address binding.
|
||||
*
|
||||
* Защита от drain-вектора: проксируемые endpoint'ы (swap-build, relay-quote) принимают
|
||||
* `userAddress`/`recipient` как body param. Если не привязать к JWT-юзеру —
|
||||
* authenticated user A может set `userAddress=<user B's addr>` и:
|
||||
* - swap output идёт к B (бесплатный slippage steal)
|
||||
* - reentrancy: B's address — malicious contract, callback дрянит
|
||||
* - bridge `recipient=attacker` → victim signs → funds to attacker
|
||||
*
|
||||
* Этот хелпер находит wallet user'а по chain и проверяет match.
|
||||
*/
|
||||
|
||||
import { WalletModel } from '../models/wallet.model';
|
||||
import type { ChainCode } from './address-validators';
|
||||
|
||||
/**
|
||||
* Throws if address ≠ user's wallet для данного chain.
|
||||
* Returns the canonical (DB-stored) address для использования вместо user input.
|
||||
*
|
||||
* Сравнение case-insensitive только для EVM (где checksum mixed-case = same address).
|
||||
* Для BTC/TRX/SOL — strict equality (base58/bech32 case-sensitive).
|
||||
*/
|
||||
export async function assertUserOwnsAddress(
|
||||
userId: string,
|
||||
chain: ChainCode,
|
||||
candidateAddress: string,
|
||||
): Promise<string> {
|
||||
const wallet = await WalletModel.findByUserAndChain(userId, chain);
|
||||
if (!wallet) {
|
||||
throw new Error(`No ${chain} wallet for user — POST /wallets/create first`);
|
||||
}
|
||||
const isEvm = chain === 'ETH' || chain === 'BSC';
|
||||
const dbAddr = wallet.address;
|
||||
const candidate = String(candidateAddress ?? '').trim();
|
||||
const match = isEvm
|
||||
? candidate.toLowerCase() === dbAddr.toLowerCase()
|
||||
: candidate === dbAddr;
|
||||
if (!match) {
|
||||
throw new Error(`Address ${candidate} does not match user's ${chain} wallet ${dbAddr}`);
|
||||
}
|
||||
return dbAddr;
|
||||
}
|
||||
Reference in New Issue
Block a user