Skip to main content

Threat Model

What Rayos protects against, what it doesn't, and why.


Core Security Guarantee​

Your funds are secured by your hardware. Not by Rayos.

The passkey that controls your wallet is generated and stored in your device's secure enclave (Apple Keychain, Android Keystore, or a hardware security key). This chip:

  • Cannot be read, even by the operating system
  • Cannot be exported or copied
  • Requires biometric or PIN verification for every use

Even if every Rayos server were hacked today, an attacker still couldn't move your funds without physical access to your device.


What Rayos Protects Against​

ThreatProtection
PhishingPasskeys are domain-bound β€” they only work on the site they were created for. A fake site gets nothing.
Password breachThere are no passwords. Can't breach what doesn't exist.
Seed phrase lossThere are no seed phrases. Your passkey is the key.
Relay server compromiseRelay can pay gas but cannot sign transactions or move funds.
Man-in-the-middlePasskey assertion is cryptographically bound to the specific challenge from the server. Replaying it fails.
Unauthorized recoveryRecovery requires N-of-M guardian signatures + timelock. Compromising one guardian is not enough.

What Rayos Does NOT Protect Against​

ThreatWhy NotMitigation
Compromised deviceIf someone has your unlocked phone, they have your passkey.Enable a strong device PIN. Enable remote wipe.
All guardians compromisedIf all your guardians are controlled by an attacker, recovery can be hijacked.Choose guardians carefully. Diversify.
Social engineeringGuardians could be tricked into approving a fraudulent recovery.Guardians should verify out-of-band before approving.
Smart contract bugsA bug in the contracts could be exploited.Independent audit is planned before mainnet.
Stellar network issuesIf Stellar is down, transactions can't be processed.This is infrastructure risk, not a Rayos flaw.

The Relay's Trust Boundary​

The relay-backend is not trusted with funds:

graph TD
U["User Device"] -->|"Signs XDR with passkey"| RELAY
RELAY -->|"Adds fee-bump only"| STELLAR["Stellar Network"]
RELAY -.->|"Cannot tamper β€” signature breaks"| BLOCKED["Attempt Blocked by Network"]

What the relay stores:

  • credential_id (public β€” equivalent to a username)
  • wallet_address (public β€” on-chain anyway)
  • WebAuthn challenges (ephemeral, 5-min TTL in Redis)
  • Session key metadata (on-chain contract is the authority)
  • Recovery proposals (on-chain contract validates execution)

What the relay never stores:

  • Private keys
  • Seed phrases
  • Raw biometric data
  • Unencrypted session secrets

Passkey Security Model​

graph LR
U["User"] -->|"Touch / Face"| SE["Secure Enclave"]
SE -->|"Signs challenge"| SIG["secp256r1 Signature"]
SIG -->|"Sent to relay"| RELAY["Relay"]
RELAY -->|"Forwarded in XDR"| CONTRACT["Wallet Contract"]
CONTRACT -->|"secp256r1_verify()"| RESULT["Valid / Invalid"]
  • The private key never leaves the secure enclave
  • The relay only sees the signature (public output)
  • The Soroban contract verifies using the public key (stored on-chain at wallet creation)
  • The Hash<32> type on the contract side ensures only the Stellar host can produce a valid payload β€” preventing replay attacks

Guardian Recovery Security​

Recovery has two independent safeguards:

  1. Threshold β€” Multiple guardians must approve (typically 2-of-3)
  2. Timelock β€” A waiting period (typically 48h) before execution

Even if an attacker compromises one guardian, they still need:

  • Enough other guardians (to meet threshold)
  • To wait out the timelock (during which the real owner can cancel)

Reporting a Vulnerability​

Please see Responsible Disclosure for how to report security issues.

Do not open a public GitHub issue for security vulnerabilities.