T09 · Insecure Skill Coding Practices
- Location
src/index.ts:241- Finding
Reusable Identity Secrets Are Disclosed to the Remote API and Public Blockchain
- Content
View full analysis
Vulnerability Details
File Location:
src/index.ts:241-246,src/index.ts:425-433,src/index.ts:576-592,src/index.ts:770-781,src/index.ts:905-913,src/index.ts:1148-1185, andsrc/index.ts:1234-1288
Vulnerability Type: Sensitive authentication material disclosure
Risk Level: HighVulnerable Code
Room creation sends Party A's identity secret to the configured API:
typescript const body = { roomId, numericRoomId: numericId, partyAIdentitySecret: identitySecret, partyAIdentityHash: identityHash, expiresIn: options.expiresIn || 3600, };Joining a room sends Party B's identity secret to the API:
typescript const body = { wallet: this.wallet.publicKey.toBase58(), partyB: this.wallet.publicKey.toBase58(), partyBIdentitySecret: identitySecret, txSignature, signature: sig, ts, };Cancellation sends both the participant identity secret and Party A's identity secret:
typescript const res = await fetch( `${this.config.apiUrl}/api/trade-rooms/cancel-onchain`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ roomId, numericRoomId: room.numericRoomId, partyAIdentityHash: room.partyAIdentityHash, partyAIdentitySecret: room.partyAIdentitySecret, isPartyA, identitySecret, partyASlots, partyBSlots, }), } );Claiming locked tokens also sends the identity secret to the service:
typescript const res = await fetch( `${this.config.apiUrl}/api/trade-rooms/claim-locked`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ roomId, numericRoomId: room.numericRoomId, partyAIdentityHash: room.partyAIdentityHash, isPartyA, identitySecret, tokenSlots, }), } );The same secre ...[truncated 3489 chars]
- Remediation
View remediation
Remediation Suggestions
- Stop including
partyAIdentitySecretandpartyBIdentitySecretin API request bodies and API responses. - Never place reusable confidential values in Solana transaction instruction data.
- Replace preimage-based authorization with wallet signatures over canonical, operation-specific payloads.
- Bind each signature to:
- The protocol and network.
- The exact action.
- The room ID.
- The participant role.
- All token, recipient, lockup, and transaction parameters.
- A server-issued nonce.
- A short expiration time.
- Enforce one-time nonce consumption and participant-role validation on the server.
- If identity commitments are a protocol requirement, use a construction that proves knowledge without revealing a reusable preimage.
- Store any unavoidable client-side secret in protected local storage and erase it after the room lifecycle ends.
- Remove identity-secret fields from
TradeRoomresponses and redact them from all application and infrastructure logs. - Rotate or invalidate existing room secrets because previously submitted transaction data may remain publicly accessible.
- Document the trust boundary introduced by the API and relayer instead of describing the complete workflow as requiring no trust.
- Stop including
