Security Practices
This guide covers security best practices when using the Newgate framework.
Input Validation
Validate All User Input
Always validate and sanitize user input before processing:
import App from 'newgatejs';
const app = new App();
app.post('/users', (req, res) => {
const { name, email, age } = req.body;
// Validate required fields
if (!name || !email) {
return res.status(400).error({
message: 'Missing required fields',
code: 400,
details: { required: ['name', 'email'] }
});
}
// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return res.status(400).error({
message: 'Invalid email format',
code: 400
});
}
// Validate age is a number
if (age && isNaN(parseInt(age))) {
return res.status(400).error({
message: 'Age must be a number',
code: 400
});
}
// Process valid data
res.json({ success: true, user: { name, email, age } });
});
CSV Schema Validation
Use CSV schema validation to enforce data types:
app.post('/import', (req, res) => {
if (req.bodyType !== 'csv') {
return res.status(400).error({
message: 'Expected CSV format',
code: 400
});
}
// Validate CSV schema
const schema = {
email: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
age: (val) => !isNaN(parseInt(val)) && parseInt(val) > 0,
status: (val) => ['active', 'inactive'].includes(val)
};
try {
const records = parseCSV(req.body, { schema });
res.json({ imported: records.length });
} catch (err) {
res.status(400).error({
message: 'CSV validation failed',
code: 400,
details: { error: err.message }
});
}
});
File Upload Security
Configure Upload Limits
Always set appropriate file upload limits to prevent DoS attacks:
import App from 'newgatejs';
const app = new App();
// Configure form-data parser with limits
const uploadOptions = {
fileSizeLimit: 5 * 1024 * 1024, // 5MB per file
memoryLimit: 50 * 1024 * 1024, // 50MB total
fileCountLimit: 5 // Max 5 files
};
Validate File Types
Check both MIME type and file extension:
import path from 'path';
function validateFile(file) {
const allowedMimes = ['image/jpeg', 'image/png', 'application/pdf'];
const allowedExts = ['.jpg', '.jpeg', '.png', '.pdf'];
// Check MIME type
if (!allowedMimes.includes(file.mimetype)) {
throw new Error(`Invalid MIME type: ${file.mimetype}`);
}
// Check file extension
const ext = path.extname(file.filename).toLowerCase();
if (!allowedExts.includes(ext)) {
throw new Error(`Invalid file extension: ${ext}`);
}
return true;
}
XML Security
XXE Protection (Enabled by Default)
XML External Entity (XXE) attacks are a common vulnerability in XML parsers. Newgate's XML parser is configured with safe defaults (external entity replacement disabled).
// Safe by default - external entities disabled
app.post('/data', (req, res) => {
if (req.bodyType === 'xml') {
// External entities are already disabled
res.json({ parsed: req.body });
}
});
CORS Configuration
Restrict Origins in Production
Always restrict CORS origins in production environments:
if (process.env.NODE_ENV === 'development') {
app.cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']
});
} else {
// Production - restrict to specific origins
app.cors({
origin: ['https://example.com', 'https://app.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
maxAge: 3600
});
}
Error Handling
Hide Sensitive Information
Never expose stack traces or internal details in production error responses:
app.useError((err, req, res, next) => {
const isDevelopment = process.env.NODE_ENV === 'development';
const errorResponse = {
error: true,
code: err.statusCode || 500,
message: isDevelopment ? err.message : 'Internal Server Error'
};
if (isDevelopment) {
errorResponse.stack = err.stack;
errorResponse.details = err.details;
}
res.status(errorResponse.code).json(errorResponse);
});
Common Vulnerabilities
SQL Injection Prevention
Use parameterized queries instead of string concatenation:
// WRONG - Vulnerable to SQL injection
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
// CORRECT - Use parameterized queries
const query = 'SELECT * FROM users WHERE id = $1';
const values = [req.params.id];
Last updated: 12/11/2025
Edit on GitHub