nehonix-uri-processor
Version:
A powerful URI processor for encoding, decoding, and analyzing URI data securely.
114 lines • 4.93 kB
JavaScript
import { randomBytes } from "crypto";
import ipRangeCheck from "ip-range-check";
import { RuleEngine } from "./RuleEngine";
import { ncu } from "../../utils/NehonixCoreUtils";
export class NehonixShield {
constructor(config) {
this.setupCSP = (req, res, next) => {
const nonce = randomBytes(16).toString("base64");
res.locals.cspNonce = nonce;
const cspDirectives = this.ruleEngine.getCSPDirectives(nonce);
res.setHeader("Content-Security-Policy", cspDirectives);
next();
};
this.csrfProtection = (req, res, next) => {
if (this.ruleEngine.shouldSkipCSRF(req)) {
return next();
}
const csrfToken = req.headers["x-csrf-token"] || req.headers["x-xsrf-token"];
const storedToken = req.cookies["csrf-token"];
if (typeof csrfToken === "string") {
if (!this.ruleEngine.validateCSRFToken(csrfToken, storedToken)) {
return res.status(403).json({ error: "CSRF token validation failed" });
}
else {
for (const crf of csrfToken) {
if (!this.ruleEngine.validateCSRFToken(crf, storedToken)) {
return res.status(403).json({ error: "CSRF token validation failed" });
}
}
}
}
next();
};
this.configureTrustedProxy = (req, res, next) => {
const clientIp = req.ip || req.connection.remoteAddress || "";
req.trusted = this.trustedProxies.includes(clientIp);
if (!req.trusted) {
delete req.headers["x-forwarded-for"];
delete req.headers["x-forwarded-proto"];
delete req.headers["x-forwarded-host"];
}
next();
};
this.secureCoookieSettings = (req, res, next) => {
const originalCookie = res.cookie;
res.cookie = (name, value, options = {}) => {
const secureOptions = this.ruleEngine.getSecureCookieOptions(options);
return originalCookie.call(res, name, value, secureOptions);
};
next();
};
this.validateRequest = async (req, res, next) => {
const url = new URL(`http://mock.nehonix.space/${req.url}`);
const urlCheckResult = await ncu.asyncCheckUrl(url.toString());
if (!urlCheckResult.isValid) {
return res.status(400).json({
error: "Suspicious or invalid URL pattern",
provider: "nehonix.shield",
result: urlCheckResult,
url: url.toString()
});
}
const contentLength = parseInt(req.headers["content-length"], 10) || 0;
if (contentLength > this.maxPayloadSize) {
return res.status(413).json({ error: "Payload too large" });
}
if (!await this.ruleEngine.validateRequest(req)) {
return res.status(400).json({ error: "Request validation failed" });
}
next();
};
this.ipFilter = (req, res, next) => {
const clientIp = req.ip || req.connection.remoteAddress || "";
if (this.bannedIPs.includes(clientIp)) {
return res.status(403).json({ error: "Access denied" });
}
for (const range of this.bannedRanges) {
if (ipRangeCheck(clientIp, range.trim())) {
return res.status(403).json({ error: "Access denied" });
}
}
if (!this.ruleEngine.validateIP(clientIp)) {
return res.status(403).json({ error: "IP validation failed" });
}
next();
};
this.additionalSecurityHeaders = (req, res, next) => {
const headers = this.ruleEngine.getSecurityHeaders(req);
Object.entries(headers).forEach(([key, value]) => {
res.setHeader(key, value);
});
next();
};
this.trustedProxies = config.trustedProxies || [];
this.bannedIPs = config.bannedIPs || [];
this.bannedRanges = config.bannedRanges || [];
this.maxPayloadSize = config.maxPayloadSize || 1000000;
this.ruleEngine = new RuleEngine(config.customRules || []);
}
applyMiddleware(app) {
app.use(this.configureTrustedProxy);
app.use(this.setupCSP);
app.use(this.secureCoookieSettings);
app.use(this.validateRequest);
app.use(this.ipFilter);
app.use(this.additionalSecurityHeaders);
app.use(this.csrfProtection);
return app;
}
loadRules(rules) {
this.ruleEngine.loadRules(rules);
}
}
//# sourceMappingURL=NehonixShield.js.map