Skip to content

[Security] Implement Request Body Size Limits, SQL Injection Prevention, and XSS Protection #30

Description

@KarenZita01

Description

To ensure the EquipChain API is hardened against common web application attacks, this issue implements three critical security measures: request body size limits to prevent denial-of-service through large payloads, SQL injection prevention patterns (defense-in-depth even without a SQL database), and cross-site scripting (XSS) protection for any user-submitted data that might be reflected in API responses.

Request Body Size Limits: Configure the Express JSON body parser with a maximum payload size of 1MB (configurable via MAX_BODY_SIZE env var). Requests exceeding this limit should receive a 413 Payload Too Large response with a clear error message. URL-encoded body parsing should also be limited. File upload endpoints (if any) should have separate, larger limits with streaming validation.

SQL Injection Prevention: Although the current MVP uses in-memory storage, the codebase should follow defense-in-depth practices: (1) All user input used in filter/search queries must be validated against expected types using Zod schemas (Issue #8). (2) Repository methods must avoid string concatenation for query building — use parameterized queries or the repository abstraction (Issue #22). (3) A linting rule should flag any direct string interpolation in database queries. (4) Input normalization (trimming, escaping special characters) should be applied in the validation layer.

XSS Protection: (1) All API responses must set Content-Type: application/json explicitly (never text/html). (2) User-submitted strings that might be reflected in error messages or responses must be sanitized using escape-html or similar. (3) Helmet (Issue #24) already sets XSS-related headers. (4) Any endpoint that accepts and returns user-controlled data must validate and encode it. (5) Log injection prevention: user-controlled data in log messages must be sanitized to prevent log forging attacks.

Technical Context & Impact

  • Dependencies: escape-html (for XSS sanitization), express built-in express.json({ limit }) for body size limits. No additional major dependencies.
  • Architecture: Body size limit configuration in src/app.js (or the middleware configuration module from Issue [Refactor] Split Monolithic index.js into Modular Express Application Structure #28). XSS sanitization utility in src/utils/sanitize.js. Linting rules in .eslintrc.json. Integration with Zod schemas for input validation.
  • Impact: Critical for production security. Body size limits prevent trivial DoS attacks. XSS protection prevents stored/reflected XSS even though the API returns JSON. SQL injection prevention is defense-in-depth for when a database is introduced.

Step-by-Step Implementation Guide

  1. Configure Body Size Limits: In src/app.js, configure express.json({ limit: process.env.MAX_BODY_SIZE || '1mb' }) and express.urlencoded({ extended: true, limit: '1mb' }). Add validation that returns 413 with JSON error body on oversized payload. Test with a request exceeding the limit.
  2. Create XSS Sanitization Utility: Write src/utils/sanitize.js exporting sanitize(str) that uses escape-html to encode HTML entities. Export sanitizeObject(obj, fields) that sanitizes specified string fields in an object. Use this utility in error response formatting and anywhere user-submitted data is reflected in responses.
  3. Add Input Normalization: Update Zod schemas (Issue [Security] Implement Input Validation with Zod Schemas and Request Sanitization #8) with .trim() on string fields to remove leading/trailing whitespace. Add .max() constraints to prevent excessively long strings (e.g., max 1000 chars for description fields). Reject control characters (null bytes, newlines in single-line fields) using .regex().
  4. Implement SQL Injection Linting Rule: Update .eslintrc.json with a custom rule or use eslint-plugin-security to detect + string concatenation or template literals in query-like patterns. Add npm install --save-dev eslint-plugin-security if needed.
  5. Validate Response Content-Type: Add a middleware or test that verifies all API responses have Content-Type: application/json (except for the Swagger UI and static files). This prevents browser MIME-type confusion.
  6. Log Injection Prevention: In the logger middleware (Issue [Middleware] Add Request Logging, Error Handling, Rate Limiting, and Request Validation Middleware #6 / [Refactor] Adopt TypeScript for Type-Safe Development Across the Codebase #16), sanitize any user-controlled data before logging. Strip newlines from log messages to prevent log forging. Configure Pino's redact option to mask sensitive fields.
  7. Write Tests: Create tests/integration/security.test.js (or extend existing from Issue [Security] Add CORS, Helmet, and Other Security Middleware for Production Hardening #24) testing: oversized payload returns 413, XSS payloads in input are sanitized in responses, response Content-Type is always JSON, sanitization of reflected error messages.

Verification & Testing Steps

  1. Send a POST request with a body exceeding MAX_BODY_SIZE (e.g., 2MB of data) — verify a 413 Payload Too Large response with JSON error body.
  2. Send a POST request with an XSS payload in a string field (e.g., <script>alert('xss')</script>) — verify the field is sanitized (HTML entities encoded) in any response that reflects it.
  3. Check all API responses for Content-Type: application/json — verify no endpoint accidentally returns text/html.
  4. Send a request with a string containing null bytes (\x00) — verify the Zod schema rejects it with a validation error (400).
  5. Send a request with a very long string (e.g., 100KB) in a field that has a max() constraint — verify a 400 validation error.
  6. Review the application logs — verify that user-controlled input in log messages does not contain raw special characters that could enable log forging.
  7. Run npx eslint . and verify the SQL injection prevention rule is active and flags any suspicious string concatenation (if any exists).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions