# Security Guide ## Overview OrbiQuant IA maneja datos financieros sensibles (fondos de usuarios, órdenes de trading, información personal) por lo que la seguridad es **crítica**. Este documento describe las medidas de seguridad implementadas y best practices. ## Threat Model ### Assets to Protect 1. **User Funds:** Dinero en wallets internos y exchanges 2. **Personal Data:** Email, nombre, dirección, documentos KYC 3. **Trading Data:** Posiciones, órdenes, estrategias 4. **API Keys:** Claves de exchanges de usuarios 5. **Financial Data:** Transacciones, balances, historial 6. **ML Models:** Modelos propietarios de predicción ### Attack Vectors 1. **Credential Theft:** Phishing, keyloggers, brute force 2. **API Abuse:** Rate limiting bypass, scraping, DDoS 3. **SQL Injection:** Malicious queries 4. **XSS:** Cross-site scripting attacks 5. **CSRF:** Cross-site request forgery 6. **Man-in-the-Middle:** Traffic interception 7. **Insider Threats:** Malicious employees 8. **Supply Chain:** Compromised dependencies ## Authentication & Authorization ### Multi-Factor Authentication (MFA) **Implementation:** TOTP (Time-based One-Time Password) using Speakeasy ```typescript // Enable 2FA POST /api/auth/2fa/enable Response: { "secret": "JBSWY3DPEHPK3PXP", "qrCode": "data:image/png;base64,..." } // Verify 2FA setup POST /api/auth/2fa/verify { "token": "123456" } // Login with 2FA POST /api/auth/login { "email": "user@example.com", "password": "password", "totpCode": "123456" // Required if 2FA enabled } ``` **Enforcement:** - Mandatory for withdrawals > $1000 - Mandatory for API key generation - Mandatory for admin accounts - Optional for regular trading ### OAuth2 Integration **Supported Providers:** - Google (OAuth 2.0) - Facebook - Apple Sign-In - GitHub **Security Features:** - State parameter for CSRF protection - PKCE (Proof Key for Code Exchange) for mobile - Token validation with provider APIs - Automatic account linking ```typescript // OAuth flow GET /api/auth/oauth/google → Redirects to Google → User authorizes → Callback to /api/auth/oauth/google/callback → Validates state and code → Exchanges code for tokens → Creates/links user account → Returns JWT ``` ### JWT (JSON Web Tokens) **Token Types:** 1. **Access Token** - Lifetime: 1 hour - Used for API requests - Stored in memory (not localStorage) 2. **Refresh Token** - Lifetime: 30 days - Used to get new access tokens - Stored in httpOnly cookie - Rotation on each use **Token Structure:** ```json { "header": { "alg": "HS256", "typ": "JWT" }, "payload": { "sub": "user-uuid", "email": "user@example.com", "role": "user", "iat": 1670832000, "exp": 1670835600 }, "signature": "..." } ``` **Security Measures:** - Strong secret (256-bit minimum) - Short-lived access tokens - Refresh token rotation - Token revocation on logout - Blacklist for compromised tokens ### Role-Based Access Control (RBAC) **Roles:** | Role | Permissions | |------|-------------| | **user** | Trading, portfolio, courses | | **premium** | Advanced features, higher limits | | **trader** | Create strategies, copy trading | | **admin** | User management, system config | | **super_admin** | Full system access | **Permission Checking:** ```typescript // Middleware const requireRole = (roles: string[]) => { return (req, res, next) => { if (!roles.includes(req.user.role)) { return res.status(403).json({ error: 'Forbidden' }); } next(); }; }; // Usage router.post('/admin/users', requireRole(['admin', 'super_admin']), createUser); ``` ### Session Management **Features:** - Device tracking (browser, OS, IP) - Active session list - Concurrent session limits (max 5) - Session revocation (logout other devices) - Automatic logout after 24h inactivity ```typescript GET /api/auth/sessions Response: { "sessions": [ { "id": "session-uuid", "device": "Chrome on Windows", "ip": "192.168.1.1", "lastActivity": "2025-12-12T10:00:00Z", "current": true } ] } DELETE /api/auth/sessions/:sessionId // Logout specific session DELETE /api/auth/sessions // Logout all except current ``` ## Data Protection ### Encryption at Rest **Database:** - PostgreSQL with pgcrypto extension - Encrypted columns for sensitive data: - API keys (AES-256) - Social security numbers - Bank account numbers - Private keys ```sql -- Encrypt API key UPDATE users SET exchange_api_key = pgp_sym_encrypt('secret_key', 'encryption_password'); -- Decrypt API key SELECT pgp_sym_decrypt(exchange_api_key, 'encryption_password') FROM users WHERE id = 'user-uuid'; ``` **File Storage:** - KYC documents encrypted with AES-256 - Encryption keys stored in AWS KMS (future) - Per-user encryption keys ### Encryption in Transit **TLS/SSL:** - Enforce HTTPS in production - TLS 1.3 minimum - Strong cipher suites only - HSTS (HTTP Strict Transport Security) **Certificate Management:** - Let's Encrypt for SSL certificates - Auto-renewal with Certbot - Certificate pinning for mobile apps ```nginx # Nginx configuration server { listen 443 ssl http2; ssl_certificate /etc/letsencrypt/live/orbiquant.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/orbiquant.com/privkey.pem; ssl_protocols TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; } ``` ### Password Security **Hashing:** - Algorithm: bcrypt - Salt rounds: 12 - Automatic rehashing on login if rounds < 12 ```typescript import bcrypt from 'bcryptjs'; // Hash password const hash = await bcrypt.hash(password, 12); // Verify password const isValid = await bcrypt.compare(password, hash); ``` **Password Policy:** - Minimum 8 characters - At least 1 uppercase letter - At least 1 lowercase letter - At least 1 number - At least 1 special character - Not in common password list - Cannot be same as email **Password Reset:** - Token valid for 1 hour only - One-time use tokens - Email verification required - Rate limited (3 attempts per hour) ### API Key Security **User API Keys (for exchanges):** - Encrypted at rest (AES-256) - Never logged - Permissions scope (read-only vs trading) - IP whitelisting option - Automatic rotation reminders **Platform API Keys (internal services):** - Separate keys per service - Stored in environment variables - Rotated every 90 days - Revoked immediately if compromised **Best Practices:** ```typescript // ❌ Bad const apiKey = "sk_live_1234567890"; logger.info(`Using API key: ${apiKey}`); // ✅ Good const apiKey = process.env.EXCHANGE_API_KEY; logger.info('Exchange API key loaded'); ``` ## Input Validation & Sanitization ### Schema Validation Using Zod for runtime type checking: ```typescript import { z } from 'zod'; const OrderSchema = z.object({ symbol: z.string().regex(/^[A-Z]{6,10}$/), side: z.enum(['BUY', 'SELL']), type: z.enum(['MARKET', 'LIMIT', 'STOP_LOSS']), quantity: z.number().positive().max(1000000), price: z.number().positive().optional(), }); // Validate input const validatedOrder = OrderSchema.parse(req.body); ``` ### SQL Injection Prevention **ORM (TypeORM):** - Parameterized queries by default - Never use raw queries with user input - Input validation before queries ```typescript // ❌ Bad (SQL Injection vulnerable) const users = await db.query(`SELECT * FROM users WHERE email = '${email}'`); // ✅ Good (Parameterized) const users = await userRepository.find({ where: { email } }); ``` ### XSS Prevention **Frontend:** - React auto-escapes by default - DOMPurify for user-generated HTML - CSP (Content Security Policy) headers **Backend:** - Sanitize HTML in user inputs - Escape output in templates - Set secure headers (Helmet.js) ```typescript import helmet from 'helmet'; import DOMPurify from 'dompurify'; // Helmet middleware app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'"], styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", "data:", "https:"], }, }, })); // Sanitize HTML const cleanHTML = DOMPurify.sanitize(userInput); ``` ### CSRF Protection **Token-based:** - CSRF tokens for state-changing requests - SameSite cookie attribute - Double-submit cookie pattern ```typescript // Generate CSRF token const csrfToken = crypto.randomBytes(32).toString('hex'); req.session.csrfToken = csrfToken; // Validate CSRF token if (req.body.csrfToken !== req.session.csrfToken) { return res.status(403).json({ error: 'Invalid CSRF token' }); } ``` ## Rate Limiting & DDoS Protection ### API Rate Limiting **Implementation:** express-rate-limit ```typescript import rateLimit from 'express-rate-limit'; // General rate limit const generalLimiter = rateLimit({ windowMs: 60 * 1000, // 1 minute max: 100, // 100 requests per minute message: 'Too many requests, please try again later', standardHeaders: true, legacyHeaders: false, }); // Auth rate limit (stricter) const authLimiter = rateLimit({ windowMs: 60 * 1000, max: 5, skipSuccessfulRequests: true, // Only count failed attempts }); // Trading rate limit const tradingLimiter = rateLimit({ windowMs: 60 * 1000, max: 60, keyGenerator: (req) => req.user.id, // Per user }); app.use('/api', generalLimiter); app.use('/api/auth', authLimiter); app.use('/api/trading', tradingLimiter); ``` ### DDoS Protection **Cloudflare (recommended for production):** - DDoS mitigation - WAF (Web Application Firewall) - Bot detection - Rate limiting at edge **Nginx:** ```nginx # Connection limits limit_conn_zone $binary_remote_addr zone=addr:10m; limit_conn addr 10; # Request rate limiting limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s; limit_req zone=req burst=20 nodelay; ``` ## Payment Security ### Stripe Integration **PCI Compliance:** - Never store credit card numbers - Use Stripe.js for card tokenization - PCI DSS SAQ-A compliance **Webhook Security:** ```typescript // Verify Stripe webhook signature const signature = req.headers['stripe-signature']; const event = stripe.webhooks.constructEvent( req.body, signature, process.env.STRIPE_WEBHOOK_SECRET ); if (event.type === 'payment_intent.succeeded') { // Handle payment } ``` **Best Practices:** - Idempotency keys for payment retries - 3D Secure for high-value transactions - Fraud detection (Stripe Radar) - Refund policies ### Cryptocurrency Payments (Future) **Security Considerations:** - HD wallets (Hierarchical Deterministic) - Multi-signature wallets - Cold storage for majority of funds - Hot wallet limits ($10k max) ## Audit Logging ### What to Log **Security Events:** - Login attempts (success/failure) - Password changes - 2FA enable/disable - API key creation/revocation - Permission changes - Suspicious activity **Financial Events:** - Deposits/withdrawals - Trades - Order placements - Balance changes **System Events:** - Errors - Service failures - Database queries (slow/failed) ### Log Format ```json { "timestamp": "2025-12-12T10:00:00.000Z", "level": "info", "event": "login_success", "userId": "user-uuid", "ip": "192.168.1.1", "userAgent": "Mozilla/5.0...", "metadata": { "2faUsed": true, "device": "Chrome on Windows" } } ``` ### Log Storage **Database Table:** `audit.api_logs` ```sql CREATE TABLE audit.api_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), user_id UUID REFERENCES auth.users(id), event_type VARCHAR(100) NOT NULL, ip_address INET, user_agent TEXT, request_path TEXT, request_method VARCHAR(10), status_code INTEGER, response_time_ms INTEGER, metadata JSONB, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_api_logs_user_id ON audit.api_logs(user_id); CREATE INDEX idx_api_logs_timestamp ON audit.api_logs(timestamp); CREATE INDEX idx_api_logs_event_type ON audit.api_logs(event_type); ``` ### Log Retention - Security logs: 1 year - Transaction logs: 7 years (regulatory) - System logs: 90 days - Archived to S3 after 30 days ## Dependency Security ### npm audit ```bash # Check for vulnerabilities npm audit # Fix vulnerabilities automatically npm audit fix # Force fix (may introduce breaking changes) npm audit fix --force ``` ### Automated Scanning **GitHub Dependabot:** - Automatic PRs for security updates - Weekly vulnerability scans **Snyk:** - Real-time vulnerability monitoring - License compliance checking ```yaml # .github/dependabot.yml version: 2 updates: - package-ecosystem: "npm" directory: "/apps/backend" schedule: interval: "weekly" open-pull-requests-limit: 10 ``` ### Supply Chain Security **Best Practices:** - Lock file commits (package-lock.json) - Verify package integrity (npm signatures) - Use package-lock.json for reproducible builds - Review new dependencies carefully - Minimize dependencies ## Infrastructure Security ### Server Hardening **Firewall (ufw):** ```bash # Allow only necessary ports ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP ufw allow 443/tcp # HTTPS ufw enable ``` **SSH:** ```bash # Disable password authentication PasswordAuthentication no PubkeyAuthentication yes # Disable root login PermitRootLogin no # Change default port Port 2222 ``` **Automatic Updates:** ```bash # Ubuntu apt install unattended-upgrades dpkg-reconfigure --priority=low unattended-upgrades ``` ### Database Security **PostgreSQL:** ```sql -- Create dedicated user with limited permissions CREATE USER orbiquant_app WITH PASSWORD 'strong_password'; GRANT CONNECT ON DATABASE orbiquant_platform TO orbiquant_app; GRANT USAGE ON SCHEMA auth, trading TO orbiquant_app; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA auth, trading TO orbiquant_app; -- Revoke public access REVOKE ALL ON DATABASE orbiquant_platform FROM PUBLIC; -- Enable SSL ssl = on ssl_cert_file = '/path/to/server.crt' ssl_key_file = '/path/to/server.key' ``` **Redis:** ```conf # Require password requirepass strong_redis_password # Bind to localhost only bind 127.0.0.1 # Disable dangerous commands rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command CONFIG "" ``` ### Container Security **Docker:** ```dockerfile # Use non-root user FROM node:18-alpine RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001 USER nodejs # Read-only file system docker run --read-only ... # Drop capabilities docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ... ``` **Docker Compose:** ```yaml services: backend: image: orbiquant-backend read_only: true security_opt: - no-new-privileges:true cap_drop: - ALL ``` ## Compliance & Regulations ### GDPR (General Data Protection Regulation) **Requirements:** - Data minimization - Right to access (download data) - Right to erasure (delete account) - Data portability - Consent management **Implementation:** ```typescript // Export user data GET /api/users/me/export Response: JSON file with all user data // Delete account (GDPR) DELETE /api/users/me - Anonymize user data - Delete PII (personally identifiable information) - Keep transaction history (regulatory) ``` ### KYC/AML (Know Your Customer / Anti-Money Laundering) **Verification Levels:** | Level | Limits | Requirements | |-------|--------|--------------| | **Level 0** | $100/day | Email verification | | **Level 1** | $1,000/day | Name, DOB, address | | **Level 2** | $10,000/day | ID document, selfie | | **Level 3** | Unlimited | Proof of address, video call | **Monitoring:** - Suspicious transaction patterns - Large withdrawals - Rapid account changes - Regulatory reporting ## Incident Response ### Security Incident Procedure 1. **Detection:** Monitoring alerts, user reports 2. **Containment:** Isolate affected systems 3. **Investigation:** Root cause analysis 4. **Remediation:** Fix vulnerability, patch systems 5. **Recovery:** Restore normal operations 6. **Post-Mortem:** Document lessons learned ### Breach Notification **Timeline:** - Internal notification: Immediate - User notification: Within 72 hours - Regulatory notification: As required by law **Template:** ``` Subject: Security Incident Notification We are writing to inform you of a security incident that may have affected your account. What happened: [Description] What data was affected: [List] What we are doing: [Actions taken] What you should do: [User actions] We sincerely apologize for this incident. ``` ## Security Checklist ### Development - [ ] Input validation on all endpoints - [ ] Parameterized SQL queries - [ ] Error messages don't leak sensitive info - [ ] Secrets in environment variables - [ ] Dependencies scanned for vulnerabilities - [ ] Code review before merge - [ ] No hardcoded credentials ### Deployment - [ ] HTTPS enforced - [ ] Security headers configured (Helmet) - [ ] Rate limiting enabled - [ ] CORS properly configured - [ ] Database backups enabled - [ ] Logging configured - [ ] Monitoring alerts set up ### Operations - [ ] Rotate API keys every 90 days - [ ] Review access logs weekly - [ ] Security patches applied within 48h - [ ] Backup tested monthly - [ ] Incident response plan updated - [ ] Team security training quarterly ## Security Contacts **Report vulnerabilities:** security@orbiquant.com **Bug Bounty Program (future):** - $100-$5000 depending on severity - Responsible disclosure required ## References - [OWASP Top 10](https://owasp.org/www-project-top-ten/) - [OWASP API Security](https://owasp.org/www-project-api-security/) - [CWE Top 25](https://cwe.mitre.org/top25/) - [PCI DSS](https://www.pcisecuritystandards.org/) - [GDPR](https://gdpr.eu/) - [Stripe Security](https://stripe.com/docs/security)