refactor: comprehensive code review fixes (security, performance, QA)
## Security Improvements - Fix timing attack in verifyApiKey with fixed 256-byte buffer - Fix sortOrder SQL injection with whitelist validation - Fix rate limiting bypass for non-Cloudflare traffic (fail-closed) - Remove stack trace exposure in error responses - Add request_id for audit trail (X-Request-ID header) - Sanitize origin header to prevent log injection - Add content-length validation for /sync endpoint (10KB limit) - Replace Math.random() with crypto.randomUUID() for sync IDs - Expand sensitive data masking patterns (8 → 18) ## Performance Improvements - Reduce rate limiter KV reads from 3 to 1 per request (66% reduction) - Increase sync batch size from 100 to 500 (80% fewer batches) - Fix health check N+1 query with efficient JOINs - Fix COUNT(*) Cartesian product with COUNT(DISTINCT) - Implement shared logger cache pattern across repositories - Add CacheService singleton pattern in recommend.ts - Add composite index for recommendation queries - Implement Anvil pricing query batching (100 per chunk) ## QA Improvements - Add BATCH_SIZE bounds validation (1-1000) - Add pagination bounds (page >= 1, MAX_OFFSET = 100000) - Add min/max range consistency validation - Add DB reference validation for singleton services - Add type guards for database result validation - Add timeout mechanism for external API calls (10-60s) - Use SUPPORTED_PROVIDERS constant instead of hardcoded list ## Removed - Remove Vault integration (using Wrangler secrets) - Remove 6-hour pricing cron (daily sync only) ## Configuration - Add idx_instance_types_specs_filter composite index - Add CORS Access-Control-Expose-Headers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,8 @@ export const RATE_LIMIT_DEFAULTS = {
|
||||
MAX_REQUESTS_INSTANCES: 100,
|
||||
/** Maximum requests per window for /sync endpoint */
|
||||
MAX_REQUESTS_SYNC: 10,
|
||||
/** Maximum requests per window for /recommend endpoint */
|
||||
MAX_REQUESTS_RECOMMEND: 50,
|
||||
} as const;
|
||||
|
||||
// ============================================================
|
||||
@@ -165,19 +167,22 @@ export type InstanceFamily = typeof INSTANCE_FAMILIES[number];
|
||||
/**
|
||||
* CORS configuration
|
||||
*
|
||||
* NOTE: localhost origin is included for development purposes.
|
||||
* In production, filter allowed origins based on environment.
|
||||
* Example: const allowedOrigins = CORS.ALLOWED_ORIGINS.filter(o => !o.includes('localhost'))
|
||||
* Security: Explicit allowed origins only. No wildcard fallback.
|
||||
* Development origins are separated and only used in development environment.
|
||||
*/
|
||||
export const CORS = {
|
||||
/** Default CORS origin */
|
||||
DEFAULT_ORIGIN: '*',
|
||||
/** Allowed origins for CORS */
|
||||
/** Default CORS origin - explicit production origin */
|
||||
DEFAULT_ORIGIN: 'https://anvil.it.com',
|
||||
/** Allowed production origins for CORS */
|
||||
ALLOWED_ORIGINS: [
|
||||
'https://anvil.it.com',
|
||||
'https://cloud.anvil.it.com',
|
||||
'https://hosting.anvil.it.com',
|
||||
'http://localhost:3000', // DEVELOPMENT ONLY - exclude in production
|
||||
] as string[],
|
||||
/** Development origins - only used when ENVIRONMENT === 'development' */
|
||||
DEVELOPMENT_ORIGINS: [
|
||||
'http://localhost:3000',
|
||||
'http://127.0.0.1:3000',
|
||||
] as string[],
|
||||
/** Max age for CORS preflight cache (24 hours) */
|
||||
MAX_AGE: '86400',
|
||||
|
||||
Reference in New Issue
Block a user