T09 · Insecure Skill Coding Practices
- Location
scripts/spandex_trade.mjs:499- Finding
Remote EIP-712 Order Data Is Signed Without Local Intent Validation
- Content
View full analysis
r.json()); if (signMsgRes.code !== 0) die(`KyberSwap sign-message failed: ${signMsgRes.message}`); const eip712Data = signMsgRes.data; // Sign + submit const signature = await walletClient.signTypedData({ domain: { ...eip712Data.domain, chainId: parseInt(eip712Data.domain.chainId) }, types: { Order: eip712Data.types.Order }, primaryType: 'Order', message: eip712Data.message, }); const createRes = await fetch(`${KYBER_LO_DOMAIN}/write/api/v1/orders`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...unsignedBody, salt: eip712Data.message.salt, signature }), }).then(r => r.json()); ``` The same pattern is used when canceling an order: ```js const cancelSignRes = await fetch(`${KYBER_LO_DOMAIN}/write/api/v1/orders/cancel-sign`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chainId: '8453', maker: account.address, orderIds: [parseInt(args['order-id'])] }), }).then(r => r.json()); if (cancelSignRes.code !== 0) die(`KyberSwap cancel-sign failed: ${cancelSignRes.message}`); const eip712Data = cancelSignRes.data; const signature = await walletClient.signTypedData({ domain: { ...eip712Data.domain, chainId: parseInt(eip712Data.domain.chainId) }, types: { CancelOrder: eip712Data.types.CancelOrder }, primaryType: 'CancelOrder', message: eip712Data.message, }); const cancelRes = await fetch(`${KYBER_LO_DOMAIN}/write/api/v1/orders/cancel`, { method: 'POST', headers: { 'Content-Type': 'applicatio ...[truncated 1938 chars]- Remediation
View remediation
