This document outlines the security measures implemented in AppMRR.
- Endpoint:
/api/add-startup - Limit: 3 requests per hour per IP address
- Protection: Prevents spam, DoS attacks, and abuse
- Implementation: In-memory rate limiting (per serverless instance)
- Headers: Returns
Retry-After,X-RateLimit-*headers
Note: For production with high traffic, consider upgrading to:
All user inputs are validated and sanitized before processing:
- Max length: 100 characters
- Sanitization: Removes HTML tags, script injection patterns, control characters
- Validation: Checks for suspicious patterns
- Max length: 500 characters
- Validation: Must be valid http/https URL
- Protection: Blocks localhost and private IP addresses (SSRF prevention)
- Max length: 50 characters
- Validation: Alphanumeric + underscores only
- Optional: Can be empty
- Max length: 50 characters
- Validation: Numeric only
- Optional: Can be empty (if website URL provided)
- Min length: 4 characters
- Max length: 100 characters
- Validation: Alphanumeric + hyphens/underscores only
- Min length: 10 characters
- Max length: 500 characters
- Validation: Must start with
sk_(secret key prefix) - Validation: Alphanumeric + underscores only
- All user inputs are sanitized to remove HTML/script tags
- JavaScript injection patterns (
javascript:,on*=) are removed - Control characters and null bytes are stripped
- Algorithm: AES-256-GCM (Galois/Counter Mode)
- Key Derivation: PBKDF2 with 100,000 iterations
- Salt: 64 bytes random per encryption
- IV: 16 bytes random per encryption
- Authentication: HMAC tag for integrity verification
Supabase RLS policies enforce access control:
- β READ startups table
- β READ revenue_metrics table
- β WRITE any table
- β READ api_keys table
- β Full access to all tables (bypasses RLS)
All sensitive data is stored in environment variables:
# Required
SUPABASE_URL=your_supabase_url
SUPABASE_SERVICE_ROLE_KEY=your_secret_api_key # Secret API key (not publishable)
ENCRYPTION_KEY=your_encryption_key_32_bytes_min
# For cron job
CRON_SECRET=your_strong_random_secretImportant: Never use PUBLIC_ prefix for sensitive variables in Astro.
- Mode:
output: 'server'in Astro config - Execution: All sensitive operations run on server
- Client: Only receives rendered HTML and public data
- API Routes: All in
/api/directory, server-only
- Internal error details are not leaked to client
- Generic error messages for unexpected failures
- Detailed errors only for API/validation issues
- All errors logged server-side for debugging
| Attack Type | Mitigation |
|---|---|
| XSS (Cross-Site Scripting) | Input sanitization, HTML tag removal |
| SQL Injection | Parameterized queries (Supabase) |
| SSRF (Server-Side Request Forgery) | URL validation, private IP blocking |
| DoS (Denial of Service) | Rate limiting |
| Data Exfiltration | RLS policies, encryption at rest |
| API Key Theft | Encrypted storage, server-only access |
| Credential Stuffing | Rate limiting, API key validation |
| Script Injection | Input sanitization, pattern blocking |
-
Test Rate Limiting:
# Should block after 3 requests for i in {1..5}; do curl -X POST https://your-domain.com/api/add-startup \ -H "Content-Type: application/json" \ -d '{"name":"test","projectId":"test1234","revenuecatApiKey":"sk_test","websiteUrl":"https://example.com"}' done
-
Test Input Validation:
# Should reject invalid inputs curl -X POST https://your-domain.com/api/add-startup \ -H "Content-Type: application/json" \ -d '{"name":"<script>alert(1)</script>","projectId":"x","websiteUrl":"javascript:alert(1)"}'
-
Test RLS Policies:
-- In Supabase SQL Editor with Publishable key SELECT * FROM api_keys; -- Should fail INSERT INTO startups (name) VALUES ('test'); -- Should fail
- Rate limiting on public endpoints
- Input validation and sanitization
- XSS protection
- RLS policies configured
- API keys encrypted at rest (AES-256-GCM)
- Environment variables secured
- SSR mode enabled
- Error messages don't leak internals
- No secrets in client bundle
- HTTPS only (enforced by Vercel)
- Secure headers (CSP, X-Frame-Options, etc.)
- Monitor rate limit abuse: Set up alerts for excessive rate limit violations
- Regular dependency updates: Run
npm auditweekly - Key rotation: Plan for encryption key rotation every 6-12 months
- Log monitoring: Review logs for suspicious patterns
- Upgrade rate limiting: Use Vercel KV or Upstash for distributed rate limiting
- Add CAPTCHA: Consider adding reCAPTCHA for signup form
- Content Security Policy: Add stricter CSP headers
- Security headers: Add additional security headers (HSTS, etc.)
- WAF (Web Application Firewall): Cloudflare or similar
- DDoS protection: Cloudflare or Vercel Pro
- Security scanning: Automated vulnerability scanning
- Penetration testing: Annual professional security audit
If you discover a security vulnerability, please email: [gonzalofsv@gmail.com]
DO NOT create public issues for security vulnerabilities.