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