XyPriss Security Guide
XyPriss includes 12 built-in security middleware modules to protect your applications from common web vulnerabilities without requiring Express.
Built-in Security Middleware
XyPriss provides the following security middleware out of the box:
- Helmet - Security headers (CSP, X-Frame-Options, HSTS, etc.)
- CORS - Cross-origin resource sharing protection
- Rate Limiting - Request throttling and abuse prevention
- CSRF - Cross-site request forgery protection using csrf-csrf
- Compression - Response compression with security considerations
- HPP - HTTP parameter pollution protection
- Mongo Sanitize - NoSQL injection protection
- XSS - Cross-site scripting protection
- Morgan - Request logging for security monitoring
- Slow Down - Progressive delay protection against abuse
- Express Brute - Brute force attack protection
- Validator - Input validation and sanitization helpers
CSRF Protection
XyPriss uses the csrf-csrf library for robust CSRF protection:
import { createServer } from "xypriss";
const app = createServer();
// CSRF protection is enabled by default
// Access middleware API to configure
app.middleware().csrf({
getSecret: () => process.env.CSRF_SECRET || "default-secret",
cookieName: "__Host-csrf-token",
cookieOptions: {
httpOnly: true,
sameSite: "strict",
secure: process.env.NODE_ENV === "production",
},
});
Security Headers (Helmet)
Comprehensive security headers protection:
app.middleware().helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true,
},
});
Rate Limiting and Abuse Prevention
Multiple layers of protection against abuse:
// Basic rate limiting
app.middleware().rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: "Too many requests from this IP",
});
// Progressive slow down
app.middleware().slowDown({
windowMs: 15 * 60 * 1000,
delayAfter: 10, // Allow 10 requests without delay
delayMs: 500, // Add 500ms delay per request after delayAfter
maxDelayMs: 5000, // Maximum delay of 5 seconds
});
Input Validation and Sanitization
Protection against injection attacks:
// XSS protection
app.middleware().xss({
whiteList: {
a: ["href"],
b: [],
i: [],
strong: [],
em: [],
},
});
// MongoDB injection protection
app.middleware().mongoSanitize({
replaceWith: "_",
});
// HTTP parameter pollution protection
app.middleware().hpp({
whitelist: ["tags", "categories"], // Allow arrays for these parameters
});
Security Configuration
Basic Security Setup
import { createServer } from "xypriss";
const server = createServer({
// Security is enabled by default
server: {
port: 3000,
},
});
Custom Security Configuration
const server = createServer({
security: {
helmet: {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
},
cors: {
origin: [
"https://docs.xypriss.nehonix.com",
"https://app.yourdomain.com",
],
credentials: true,
methods: ["GET", "POST", "PUT", "DELETE"],
},
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests from this IP",
},
},
});
XyPriss Security Module Integration
Installation
npm install xypriss-security
Basic Integration
import { createServer } from "xypriss";
import {
XyPrissSecurity,
fString,
fArray,
fObject,
generateSecureToken,
} from "xypriss-security";
const server = createServer();
// Secure route example
server.post("/api/secure-data", async (req, res) => {
try {
// Use secure data structures
const secureData = fArray(req.body.items);
const secureMessage = fString(req.body.message, {
protectionLevel: "maximum",
enableEncryption: true,
});
// Generate secure token
const token = generateSecureToken({
length: 32,
entropy: "maximum",
});
res.json({
success: true,
token,
itemCount: secureData.length,
});
} catch (error) {
res.status(500).json({ error: "Security operation failed" });
}
});
Authentication and Authorization
JWT Authentication Example
import jwt from "jsonwebtoken";
import { Hash } from "xypriss-security";
const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key";
// Login endpoint
server.post("/auth/login", async (req, res) => {
const { username, password } = req.body;
// Validate input
if (!username || !password) {
return res
.status(400)
.json({ error: "Username and password required" });
}
// Hash password for comparison (use proper password hashing in production)
const hashedPassword = Hash.create(password, { algorithm: "sha256" });
// Verify user (implement your user verification logic)
const user = await verifyUser(username, hashedPassword);
if (!user) {
return res.status(401).json({ error: "Invalid credentials" });
}
// Generate JWT token
const token = jwt.sign(
{ userId: user.id, username: user.username },
JWT_SECRET,
{ expiresIn: "1h" }
);
res.json({ token, user: { id: user.id, username: user.username } });
});
// Authentication middleware
function authenticateToken(req, res, next) {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
if (!token) {
return res.status(401).json({ error: "Access token required" });
}
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ error: "Invalid token" });
}
req.user = user;
next();
});
}
// Protected route
server.get("/api/protected", authenticateToken, (req, res) => {
res.json({ message: "This is protected data", user: req.user });
});
Password Security
Secure Password Hashing
import { Password } from "xypriss-security";
// Hash password during registration
server.post("/auth/register", async (req, res) => {
const { username, password } = req.body;
// Validate password strength
const strength = Password.checkStrength(password);
if (strength.score < 3) {
return res.status(400).json({
error: "Password too weak",
feedback: strength.feedback,
});
}
// Hash password with Argon2ID
const hashedPassword = await Password.hash(password, {
algorithm: "argon2id",
memoryCost: 65536,
timeCost: 3,
parallelism: 4,
});
// Save user (implement your user storage logic)
const user = await createUser(username, hashedPassword);
res.json({ message: "User created successfully", userId: user.id });
});
// Verify password during login
server.post("/auth/login", async (req, res) => {
const { username, password } = req.body;
// Get user from database
const user = await getUserByUsername(username);
if (!user) {
return res.status(401).json({ error: "Invalid credentials" });
}
// Verify password
const isValid = await Password.verify(password, user.hashedPassword);
if (!isValid) {
return res.status(401).json({ error: "Invalid credentials" });
}
// Generate session token
const token = generateSecureToken({
length: 32,
entropy: "maximum",
});
res.json({ token, user: { id: user.id, username: user.username } });
});
Data Encryption
Encrypting Sensitive Data
import { XyPrissSecurity, fObject } from "xypriss-security";
// Store encrypted user data
server.post("/api/user-data", authenticateToken, async (req, res) => {
const userId = req.user.userId;
const sensitiveData = req.body;
// Create secure object for sensitive data
const secureUserData = fObject(sensitiveData, {
enableEncryption: true,
encryptionKey: process.env.DATA_ENCRYPTION_KEY,
});
// Store in database (the data will be encrypted)
await saveUserData(userId, secureUserData.serialize());
res.json({ message: "Data saved securely" });
});
// Retrieve and decrypt user data
server.get("/api/user-data", authenticateToken, async (req, res) => {
const userId = req.user.userId;
// Retrieve encrypted data from database
const encryptedData = await getUserData(userId);
// Decrypt data
const secureUserData = fObject.deserialize(encryptedData, {
encryptionKey: process.env.DATA_ENCRYPTION_KEY,
});
res.json(secureUserData.toPlainObject());
});
Input Validation and Sanitization
Request Validation
import { Validators } from "xypriss-security";
// Validation middleware
function validateInput(rules) {
return (req, res, next) => {
const validation = Validators.validate(req.body, rules);
if (!validation.isValid) {
return res.status(400).json({
error: "Validation failed",
details: validation.errors,
});
}
// Use sanitized values
req.body = validation.sanitizedValue;
next();
};
}
// Use validation middleware
server.post(
"/api/users",
validateInput({
username: {
type: "string",
required: true,
minLength: 3,
maxLength: 50,
pattern: /^[a-zA-Z0-9_]+$/,
sanitize: true,
},
email: {
type: "email",
required: true,
sanitize: true,
},
age: {
type: "number",
min: 13,
max: 120,
},
}),
(req, res) => {
// req.body now contains validated and sanitized data
res.json({ message: "User data is valid" });
}
);
Security Middleware
Custom Security Middleware
// Rate limiting per user
function userRateLimit(maxRequests = 100, windowMs = 15 * 60 * 1000) {
const userRequests = new Map();
return (req, res, next) => {
const userId = req.user?.userId;
if (!userId) return next();
const now = Date.now();
const userKey = `user:${userId}`;
if (!userRequests.has(userKey)) {
userRequests.set(userKey, { count: 1, resetTime: now + windowMs });
return next();
}
const userData = userRequests.get(userKey);
if (now > userData.resetTime) {
userData.count = 1;
userData.resetTime = now + windowMs;
return next();
}
if (userData.count >= maxRequests) {
return res.status(429).json({ error: "Rate limit exceeded" });
}
userData.count++;
next();
};
}
// Apply user-specific rate limiting
server.use("/api", authenticateToken, userRateLimit(50, 60000));
Security Headers
Custom Security Headers
// Security headers middleware
function securityHeaders(req, res, next) {
// Prevent clickjacking
res.setHeader("X-Frame-Options", "DENY");
// Prevent MIME type sniffing
res.setHeader("X-Content-Type-Options", "nosniff");
// Enable XSS protection
res.setHeader("X-XSS-Protection", "1; mode=block");
// Strict transport security
res.setHeader(
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains"
);
// Content security policy
res.setHeader("Content-Security-Policy", "default-src 'self'");
// Referrer policy
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
next();
}
server.use(securityHeaders);
Audit Logging
Security Event Logging
import { TamperEvidentLogger } from "xypriss-security";
const auditLogger = new TamperEvidentLogger({
secretKey: process.env.AUDIT_SECRET_KEY,
logFile: "security-audit.log",
});
// Log security events
async function logSecurityEvent(event, details) {
await auditLogger.log("security", event, {
timestamp: new Date().toISOString(),
...details,
});
}
// Login attempt logging
server.post("/auth/login", async (req, res) => {
const { username } = req.body;
const clientIP = req.ip;
try {
// ... authentication logic ...
await logSecurityEvent("login_success", {
username,
clientIP,
userAgent: req.get("User-Agent"),
});
res.json({ token });
} catch (error) {
await logSecurityEvent("login_failure", {
username,
clientIP,
error: error.message,
userAgent: req.get("User-Agent"),
});
res.status(401).json({ error: "Authentication failed" });
}
});
Security Best Practices
1. Environment Variables
# Use strong, unique secrets
JWT_SECRET=your-very-long-random-secret-key
DATA_ENCRYPTION_KEY=another-long-random-key
AUDIT_SECRET_KEY=audit-specific-secret-key
# Database credentials
DB_PASSWORD=secure-database-password
# API keys
EXTERNAL_API_KEY=your-external-api-key
2. HTTPS Configuration
import https from "https";
import fs from "fs";
const server = createServer();
// HTTPS server
const httpsServer = https.createServer(
{
key: fs.readFileSync("path/to/private-key.pem"),
cert: fs.readFileSync("path/to/certificate.pem"),
},
server
);
httpsServer.listen(443, () => {
console.log("HTTPS server running on port 443");
});
// Redirect HTTP to HTTPS
const httpServer = createServer();
httpServer.use((req, res) => {
res.redirect(301, `https://${req.headers.host}${req.url}`);
});
httpServer.listen(80);
3. Error Handling
// Secure error handling
server.use((err, req, res, next) => {
// Log error securely
console.error("Error:", err.message);
// Don't expose internal errors in production
const isDevelopment = process.env.NODE_ENV === "development";
res.status(err.status || 500).json({
error: isDevelopment ? err.message : "Internal server error",
stack: isDevelopment ? err.stack : undefined,
});
});
4. Security Monitoring
// Monitor suspicious activity
function securityMonitoring(req, res, next) {
const suspiciousPatterns = [
/\.\.\//, // Directory traversal
/<script/i, // XSS attempts
/union.*select/i, // SQL injection
];
const requestData = JSON.stringify(req.body) + req.url;
for (const pattern of suspiciousPatterns) {
if (pattern.test(requestData)) {
logSecurityEvent("suspicious_request", {
pattern: pattern.toString(),
url: req.url,
body: req.body,
clientIP: req.ip,
});
return res.status(400).json({ error: "Invalid request" });
}
}
next();
}
server.use(securityMonitoring);
Security Checklist
- Use HTTPS in production
- Implement proper authentication
- Hash passwords with strong algorithms (Argon2ID)
- Validate and sanitize all inputs
- Use security headers (Helmet)
- Implement rate limiting
- Log security events
- Keep dependencies updated
- Use environment variables for secrets
- Implement proper error handling
- Monitor for suspicious activity
- Regular security audits
- Use XyPriss Security module for sensitive operations
Following these security practices will help ensure your XyPriss applications are secure and resilient against common attacks. Send your message via email "xypriss-support@nehonix.com"