Gateway Pairing Mechanism
The gateway requires pairing before accepting webhook requests. This prevents unauthorized access when the gateway is accidentally exposed.How Pairing Works
- Startup — Gateway generates a 6-digit one-time pairing code
- Display — Code is printed to the terminal (only visible to operator)
- Exchange — Client sends code to
POST /pairviaX-Pairing-Codeheader - Token Generation — Server responds with a bearer token (256-bit entropy)
- Persistence — Token hash is saved to
config.tomlfor restarts
Configuration
Pairing Code Generation
The 6-digit code is generated using cryptographically secure randomness:- Source: UUID v4 (backed by OS CSPRNG)
- Linux:
/dev/urandom - Windows:
BCryptGenRandom - macOS:
SecRandomCopyBytes
- Linux:
- Entropy: 256 bits from UUID
- Range:
000000to999999(1 million possibilities) - Bias Elimination: Rejection sampling for uniform distribution
- One-Time: Consumed after first successful pair
Bearer Token Format
Generation:- Prefix:
zc_(Corvus token identifier) - Payload: 32 random bytes (256-bit entropy) hex-encoded
- Total Length: 67 characters
- Source:
rand::rng()OS CSPRNG
- Tokens are hashed with SHA-256 before storage
- Config file stores 64-character hex hashes, not plaintext
- Prevents token exposure via config file access
Brute Force Protection
Attempt Limiting:- Maximum 5 failed pairing attempts
- 5-minute lockout after max attempts
- Lockout timer returns remaining seconds
- Per-client rate limiting on
/pairendpoint - Client identified by IP + headers
- Prevents distributed brute force attacks
- Token and code comparison uses
subtle::ConstantTimeEq - Prevents timing attacks
- No early return on mismatch
Bearer Token Authentication
All authenticated endpoints require a bearer token in theAuthorization header.
Protected Endpoints
POST /webhook
GET /admin/configGET /admin/identityPATCH /admin/identity
Public Endpoints
GET /health — Always public, no auth required
Token Validation
When a request arrives:- Extract token from
Authorization: Bearer <token>header - Hash token with SHA-256
- Compare hash against stored hashes (constant-time)
- Allow or deny request based on match
Token Lifecycle
Creation:- Generated on first successful pairing
- Displayed once to client
- Never shown again (hash stored)
- Saved to
config.tomlas SHA-256 hash - Survives gateway restarts
- Multiple tokens supported
- Edit
config.tomland remove token hash - Restart gateway to apply changes
- Future:
corvus gateway unpaircommand
Public Bind Restrictions
The gateway refuses to bind to public addresses without explicit configuration or an active tunnel.Default Behavior
0.0.0.0(all interfaces)- Public IP addresses
- Non-localhost hostnames
127.0.0.1(IPv4 localhost)localhost(hostname)::1(IPv6 localhost)[::1](IPv6 localhost with brackets)
Public Bind Detection
The gateway checks the bind address before starting:- Check if a tunnel is active
- Check if
allow_public_bind = true - Refuse to start if neither is true
Allowing Public Bind
- Internal networks behind a firewall
- Development environments with additional security layers
- Situations where a tunnel is not feasible
Random Port Mode
For additional security, use a random ephemeral port:- Port scanners won’t find a known port
- Reduces attack surface
- Suitable for tunnel-only access
Tunnel Requirements
For external access, Corvus requires a tunnel instead of public bind.Supported Tunnels
Tailscale
- Zero-config HTTPS
- Tailnet authentication
- Built-in access control
Cloudflare Tunnel
ngrok
Custom Tunnel
- Check if tunnel process is running
- Allow public bind if tunnel is active
- Refuse if tunnel is not running
Security Checklist
Before exposing your gateway:- Pairing enabled —
require_pairing = true - Tunnel configured — Use Tailscale, Cloudflare, or ngrok
- Localhost bind — Avoid
allow_public_bind = true - Strong tokens — Never manually create weak tokens
- Channel allowlists — Configure sender allowlists
- HTTPS only — Tunnels provide TLS encryption
- Rate limiting — Default rate limits enabled
- Audit logs — Monitor
tracingoutput
Gateway API Reference
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/health | GET | None | Health check |
/pair | POST | X-Pairing-Code | Exchange code for token |
/webhook | POST | Bearer <token> | Send message to agent |
/whatsapp | GET | Query params | WhatsApp webhook verification |
/whatsapp | POST | Meta signature | WhatsApp incoming message |
Example: Pairing Flow
Next Steps
Security Overview
Security architecture and principles
Deployment
Production deployment guide