/** * Security middleware collection. * Extracted from server.js -- security headers, keep-alive, domain restriction, * and JSON parse error handler. */ // Security headers (minimal set -- replaces Helmet) function securityHeaders(req, res, next) { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '0'); // Disabled per OWASP recommendation (use CSP instead) res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin'); res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()'); next(); } // Middleware pour ajouter les headers Keep-Alive function keepAliveHeaders(req, res, next) { res.setHeader('Connection', 'keep-alive'); res.setHeader('Keep-Alive', 'timeout=60, max=1000'); next(); } // Middleware de restriction de domaine et réponse fake pour route spécifique function domainRestriction(req, res, next) { // Autoriser les endpoints LiveTV pour l'extension if (req.path.startsWith('/api/livetv/')) { return next(); } // Autoriser les endpoints OAuth pour les clients externes (CORS géré par le routeur OAuth) if (req.path.startsWith('/api/oauth/')) { return next(); } // Autoriser le callback serveur-à-serveur PayGate sans dépendre d'un Origin/Referer navigateur if (req.path === '/api/vip/paygate/callback') { return next(); } const allowedDomains = [ 'localhost:3000', 'movix.date', 'movix.chat', 'movix.cloud', 'movix.cash', 'movix.blog', 'movix.rodeo', 'movix.club', 'movix.site', 'movix11.pages.dev', 'nakios.site', 'cinezo.site', 'filmib.cc' ]; const origin = req.get('origin'); const referer = req.get('referer'); let isAllowed = false; // Strict domain verification const checkDomain = (url) => { try { if (!url) return false; const hostname = new URL(url).hostname; // Allow exact matches or subdomains if needed (here we list full domains) return allowedDomains.some(domain => { // Handle localhost with port special case if needed, or just match hostname if (domain.includes(':')) return url.includes(domain); return hostname === domain || hostname.endsWith('.' + domain); }); } catch (e) { return false; } }; if (origin) { if (checkDomain(origin)) isAllowed = true; } else if (referer) { if (checkDomain(referer)) isAllowed = true; } // Si autorisé, on continue if (isAllowed) { return next(); } // Si non autorisé // Route spécifique accessible mais avec fausse réponse if (req.path.startsWith('/api/imdb/movie')) { return res.json({ "iframe_src": "https://movixfakesite.vercel.app/", "player_links": [ { "player": "supervideo", "link": "https://movixfakesite.vercel.app/", "is_hd": false }, { "player": "dropload", "link": "https://movixfakesite.vercel.app/", "is_hd": false }, { "player": "mixdrop", "link": "https://movixfakesite.vercel.app/", "is_hd": false } ] }); } else if (req.path.startsWith('/api/imdb/tv')) { return res.json({ "type": "tv", "series": [ { "title": "Stranger Things - Saison 5", "audio_type": "VF", "episode_count": 1, "release_date": "2016", "summary": "Quand un jeune garçon disparaît, une petite ville découvre une affaire mystérieuse, des expériences secrètes, des forces surnaturelles terrifiantes... et une fillette.", "tmdb_data": { "id": 66732, "name": "Stranger Things", "overview": "When a young boy vanishes, a small town uncovers a mystery involving secret experiments, terrifying supernatural forces, and one strange little girl.", "first_air_date": "2016-07-15", "poster_path": "/uOOtwVbSr4QDjAGIifLDwpb2Pdl.jpg", "backdrop_path": "/8zbAoryWbtH0DKdev8abFAjdufy.jpg", "vote_average": 8.59, "match_score": 0.8818181818181817 }, "seasons": [ { "number": 1, "title": "Saison 1", "episodes": [ { "number": "1", "versions": { "vf": { "title": "Episode 1", "players": [ { "name": "Supervideo", "link": "https://movixfakesite.vercel.app/" } ] } } } ] } ] } ] }); } // Bloquer toutes les autres routes return res.status(404).json({ error: 'Not Found' }); } // Error handler for JSON parsing errors (malformed requests like URL-encoded form data) function jsonParseErrorHandler(err, req, res, next) { if (err.type === 'entity.parse.failed') { // Silently handle malformed JSON requests (likely bots or scanners) return res.status(400).json({ success: false, error: 'Invalid JSON body' }); } next(err); } module.exports = { securityHeaders, keepAliveHeaders, domainRestriction, jsonParseErrorHandler };