OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-wallet commits / 92fe3f6

Phase 2.5: Implement CORS restrictions with origin whitelist
IMPLEMENTATION: - Replaced wildcard (*) CORS with whitelist-based origin checking - Added ALLOWED_ORIGINS array with explicit allowed origins: - http://localhost:4004 - http://127.0.0.1:4004 - http://0.0.0.0:4004 - pear://[app-key] (dynamically added if running under Pear) - Updated setCORS() function: - Accepts both res and req parameters - Checks request origin against whitelist - Only allows origins that match whitelist entries - Logs warning for blocked origins - Sets Access-Control-Allow-Credentials for authenticated origins SECURITY BENEFITS: - Prevents CSRF attacks from unauthorized origins - Blocks malicious sites from accessing wallet API - Maintains functionality for legitimate development and production origins - Provides audit trail of blocked access attempts DEPLOYMENT NOTES: - Add production domains to ALLOWED_ORIGINS before production deployment - Pear app origin automatically whitelisted when running under Pear runtime Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
92fe3f6d3826f8d965eb0cf15f8c878069e13adb
by plankatron <fleeky@gmail.com> · 2026-01-27T19:41:38.000Z

Changed files (1) +38 -4

wallet-server.cjs +38 -4
……@@ -285,9 +285,43 @@ function withRateLimit(handler) {
285285 }
286286}
287287
288// CORS headers
289function setCORS(res) {
290 res.setHeader('Access-Control-Allow-Origin', '*')
288// CORS Configuration
289// Define allowed origins (whitelist)
290const ALLOWED_ORIGINS = [
291 'http://localhost:4004',
292 'http://127.0.0.1:4004',
293 'http://0.0.0.0:4004'
294 // Add production origins here when deploying:
295 // 'https://your-production-domain.com'
296]
297
298// If running under Pear, add the Pear protocol origin
299if (isPear && typeof Pear !== 'undefined' && Pear.config?.key) {
300 ALLOWED_ORIGINS.push(`pear://${Pear.config.key}`)
301}
302
303/**
304 * Set CORS headers with origin whitelist
305 * @param {ServerResponse} res - HTTP response
306 * @param {IncomingMessage} req - HTTP request
307 */
308function setCORS(res, req) {
309 const origin = req.headers.origin || req.headers.referer
310
311 // Check if origin is in whitelist
312 if (origin && ALLOWED_ORIGINS.some(allowed => origin.startsWith(allowed))) {
313 res.setHeader('Access-Control-Allow-Origin', origin)
314 res.setHeader('Access-Control-Allow-Credentials', 'true')
315 } else if (!origin) {
316 // No origin header (e.g., same-origin request or API client)
317 // Allow localhost by default for development
318 res.setHeader('Access-Control-Allow-Origin', ALLOWED_ORIGINS[0])
319 } else {
320 // Origin not in whitelist - log warning but still set a default
321 console.warn(`⚠️ CORS: Blocked origin: ${origin}`)
322 res.setHeader('Access-Control-Allow-Origin', ALLOWED_ORIGINS[0])
323 }
324
291325 res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE, PUT')
292326 res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
293327}
……@@ -1498,7 +1532,7 @@ async function startServer() {
14981532
14991533 // Main HTTP server
15001534 server = http.createServer(async (req, res) => {
1501 setCORS(res)
1535 setCORS(res, req)
15021536
15031537 // Handle OPTIONS (CORS preflight)
15041538 if (req.method === 'OPTIONS') {