UNPKG

nehonix-uri-processor

Version:

A powerful URI processor for encoding, decoding, and analyzing URI data securely.

158 lines 5.92 kB
import { randomBytes } from "crypto"; import ipRangeCheck from "ip-range-check"; import { ncu } from "../../../utils/NehonixCoreUtils"; /** * Content Security Policy middleware * Helps prevent XSS, clickjacking, and other code injection attacks */ export const setupCSP = (req, res, next) => { // Generate a nonce for inline scripts (if needed) const nonce = randomBytes(16).toString("base64"); res.locals.cspNonce = nonce; // Set CSP header with appropriate directives res.setHeader("Content-Security-Policy", `default-src 'self'; script-src 'self' 'nonce-${nonce}' https://trusted-cdn.com; style-src 'self' https://trusted-cdn.com; img-src 'self' data: https://trusted-cdn.com; font-src 'self' https://trusted-cdn.com; connect-src 'self' https://api.yourdomain.com; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; object-src 'none'`); next(); }; /** * CSRF Protection middleware * Validates that requests with cookies are from your site */ export const csrfProtection = (req, res, next) => { // Skip for non-state-changing methods if (["GET", "HEAD", "OPTIONS"].includes(req.method)) { return next(); } const csrfToken = req.headers["x-csrf-token"] || req.headers["x-xsrf-token"]; const storedToken = req.cookies["csrf-token"]; if (!csrfToken || !storedToken || csrfToken !== storedToken) { return res.status(403).json({ error: "CSRF token validation failed" }); } next(); }; /** * Trusted Proxy Configuration * Ensures X-Forwarded-* headers are only trusted from known proxies */ export const configureTrustedProxy = (req, res, next) => { var _a, _b; const trustedProxies = ((_b = (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.TRUSTED_PROXIES) === null || _b === void 0 ? void 0 : _b.split(",")) || []; const clientIp = req.ip || req.connection.remoteAddress || ""; // Only trust X-Forwarded-* headers if request comes from trusted proxy if (trustedProxies.includes(clientIp)) { req.trusted = true; } else { req.trusted = false; // Don't trust headers that might be spoofed delete req.headers["x-forwarded-for"]; delete req.headers["x-forwarded-proto"]; delete req.headers["x-forwarded-host"]; } next(); }; /** * Secure Cookie Settings * Enhances cookie security beyond the basics */ export const secureCoookieSettings = (req, res, next) => { // Override res.cookie to enforce secure settings const originalCookie = res.cookie; res.cookie = function (name, value, options = {}) { const secureOptions = { ...options, httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "strict", }; return originalCookie.call(this, name, value, secureOptions); }; next(); }; /** * Request Validation middleware * Validates incoming requests for required fields and proper formatting */ export const validateRequest = (req, res, next) => { // Check for suspicious patterns in URL const url = req.originalUrl; const checkUrl = ncu.asyncCheckUrl(url); checkUrl.then((result) => { if (!result.isValid) { return res.status(400).json({ error: "Suspicious or invalid URL pattern.", provider: "nehonix.shield", result, }); } }); // Check for overly large payloads (additional check beyond express.json limit) const contentLength = parseInt(req.headers["content-length"], 10) || 0; if (contentLength > 1000000) { // 1MB return res.status(413).json({ error: "Payload too large" }); } next(); }; /** * IP Filtering middleware * Blocks requests from suspicious or banned IP addresses */ export const ipFilter = (req, res, next) => { var _a, _b; const clientIp = req.ip || req.connection.remoteAddress || ""; // Get banned IPs and ranges from environment or configuration const bannedIPs = ((_a = process.env.BANNED_IPS) === null || _a === void 0 ? void 0 : _a.split(",")) || []; const bannedRanges = ((_b = process.env.BANNED_IP_RANGES) === null || _b === void 0 ? void 0 : _b.split(",")) || []; // Check if IP is in banned list if (bannedIPs.includes(clientIp)) { return res.status(403).json({ error: "Access denied" }); } // Check if IP is in banned range for (const range of bannedRanges) { if (ipRangeCheck(clientIp, range.trim())) { return res.status(403).json({ error: "Access denied" }); } } next(); }; /** * Security Headers middleware * Sets additional security headers beyond what Helmet provides */ export const additionalSecurityHeaders = (req, res, next) => { // Permissions Policy (formerly Feature Policy) res.setHeader("Permissions-Policy", "geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()"); // Clear Site Data on logout routes if (req.path.includes("/logout")) { res.setHeader("Clear-Site-Data", '"cache", "cookies", "storage"'); } // Cross-Origin Resource Policy res.setHeader("Cross-Origin-Resource-Policy", "same-origin"); // Cross-Origin Opener Policy res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); next(); }; /** * Apply all security middleware to an Express application */ export const applySecurityMiddleware = (app) => { // Apply all security middleware app.use(configureTrustedProxy); app.use(setupCSP); app.use(secureCoookieSettings); app.use(validateRequest); app.use(ipFilter); app.use(additionalSecurityHeaders); app.use(csrfProtection); return app; }; //# sourceMappingURL=EXPRESS.shield.js.map