Security

Non-custodial by design.

WingsyPrivate holds no assets and no keys. Here is the threat model and the controls that back it.

Wallet access is read-only

  • The EVM layer (wagmi + viem) is configured with connect and signMessage only. No transaction, approval or typed-data signing path exists in the codebase.
  • The Solana bridge exposes connect, signMessage and disconnect for Phantom and Solflare. Nothing else.
  • Watch-only addresses can be added without any signature; their assets are labelled “source-linked” rather than “verified”.

Sign-in challenge

A challenge is issued by POST /api/auth/wallet/nonce, stored with a 10-minute expiry, and consumed on first use. The server re-derives the expected statement and rejects any signature over a different message. EVM signatures are verified with viem; Solana signatures are verified as Ed25519 with node:crypto.

Encryption of private fields

  • Algorithm: AES-256-GCM with a random 96-bit IV per value and a 128-bit authentication tag. Implemented with node:crypto — no custom cryptography.
  • Key: WINGSY_ENCRYPTION_KEY (32 bytes). If unset, a key is derived from AUTH_SECRET with SHA-256 and a domain-separation label. Set the dedicated key in production so secrets can rotate independently.
  • Additional authenticated data binds each ciphertext to the owning user and column. Copying a value between rows fails to decrypt.
  • Serial numbers are searchable through an HMAC blind index — exact match only, no decryption needed.

Authorization

Every private handler calls requireUser() and scopes the query with the session user id. Objects are looked up with where: { id, userId }, so an id that belongs to someone else is indistinguishable from a missing row.

Transport and headers

  • Session cookies are httpOnly, SameSite=Lax and Secure in production.
  • Private routes and API responses are served with Cache-Control: private, no-store.
  • X-Content-Type-Options, X-Frame-Options, Referrer-Policy and Permissions-Policy headers are set globally.
  • Robots are told not to index /app, /asset and /api.

Reporting

Found a problem? Open an issue on the repository or contact the maintainers privately before disclosure.