ESLint InterlaceESLint Interlace
Plugin: lambda-securityRules

no-unvalidated-event-body

ESLint rule documentation for no-unvalidated-event-body

📡 Live from GitHub — This documentation is fetched directly from no-unvalidated-event-body.md and cached for 6 hours.

Keywords: input validation, event body, injection, CWE-20, Lambda, Zod, Joi, Middy, serverless CWE: CWE-20
OWASP: A03:2021-Injection

Detect Lambda handlers using event body without validation

Detects Lambda handlers that use event body, query parameters, or path parameters without validation. This rule is part of eslint-plugin-lambda-security and provides LLM-optimized error messages.

🚨 Security rule | 💡 Provides suggestions | ⚠️ Set to error in recommended

Quick Summary

AspectDetails
CWE ReferenceCWE-20 (Input Validation)
CVSS Score8.0 High
Auto-Fix💡 Suggests schema validation
CategorySecurity
Best ForLambda functions processing user input

Vulnerability and Risk

Vulnerability: Using untrusted input from Lambda events without validation can lead to injection attacks, type confusion, and business logic bypasses.

Risk: Unvalidated input enables:

  • NoSQL injection attacks
  • SQL injection in downstream services
  • Command injection via shell commands
  • Business logic manipulation
  • Type confusion vulnerabilities

Rule Details

This rule detects direct usage of these event properties without passing through validation functions:

  • event.body
  • event.queryStringParameters
  • event.pathParameters
  • event.headers
  • event.multiValueQueryStringParameters

Why This Matters

RiskImpactSolution
💉 InjectionDatabase/command injection attacksValidate with schema library
📊 Type ConfusionUnexpected data types break logicUse typed validation
🔓 Auth BypassManipulated fields bypass checksStrict schema enforcement

Configuration

OptionTypeDefaultDescription
allowInTestsbooleantrueAllow in test files
additionalPropertiesstring[][]Additional event properties to check
{
  rules: {
    'lambda-security/no-unvalidated-event-body': ['error', {
      allowInTests: true,
      additionalProperties: ['customProperty']
    }]
  }
}

Examples

❌ Incorrect

export const handler = async (event) => {
  const body = JSON.parse(event.body); // ❌ No validation
  const userId = body.userId; // Trusting user input

  const item = await db.get({ userId }); // Could be injection

  // Query params used directly
  const limit = event.queryStringParameters.limit; // ❌ Could be "1; DROP TABLE"

  return { statusCode: 200, body: JSON.stringify(item) };
};

✅ Correct with Zod

import { z } from 'zod';

const RequestSchema = z.object({
  userId: z.string().uuid(),
  action: z.enum(['read', 'write', 'delete']),
});

export const handler = async (event) => {
  const body = JSON.parse(event.body ?? '{}');

  // Validate with Zod
  const validatedData = RequestSchema.parse(body); // ✅ Validated

  const item = await db.get({ userId: validatedData.userId });
  return { statusCode: 200, body: JSON.stringify(item) };
};

✅ Correct with Middy Validator

import middy from '@middy/core';
import jsonBodyParser from '@middy/http-json-body-parser';
import validator from '@middy/validator';
import { transpileSchema } from '@middy/validator/transpile';

const inputSchema = transpileSchema({
  type: 'object',
  required: ['body'],
  properties: {
    body: {
      type: 'object',
      required: ['userId'],
      properties: {
        userId: { type: 'string', format: 'uuid' },
      },
    },
  },
});

const baseHandler = async (event) => {
  // event.body is now validated ✅
  const { userId } = event.body;
  return { statusCode: 200, body: JSON.stringify({ userId }) };
};

export const handler = middy(baseHandler)
  .use(jsonBodyParser())
  .use(validator({ inputSchema })); // ✅ Middy validation

✅ Correct with Joi

import Joi from 'joi';

const schema = Joi.object({
  userId: Joi.string().uuid().required(),
  email: Joi.string().email().required(),
});

export const handler = async (event) => {
  const body = JSON.parse(event.body ?? '{}');

  const { error, value } = schema.validate(body); // ✅ Validated
  if (error) {
    return { statusCode: 400, body: JSON.stringify({ error: error.message }) };
  }

  await processUser(value);
  return { statusCode: 200 };
};

Validation Libraries

LibraryType SafetyPerformanceEcosystem
Zod✅ ExcellentGoodTypeScript-first
Joi⚠️ ManualGoodNode.js standard
Yup⚠️ ManualGoodReact forms
Middy⚠️ ManualExcellentLambda middleware
class-validator✅ GoodModerateNestJS

Security Impact

VulnerabilityCWEOWASPCVSSImpact
Input Validation20A03:20218.0 HighInjection attacks
Improper Neutralization74A03:20217.5 HighCommand/query injection

Safe Patterns (Not Flagged)

// Type checking
if (typeof event.body === 'string') { ... }

// Null checking
if (event.body) { ... }

// Optional chaining
const name = event.body?.name;

// Logging (not using the data)
console.log('Received event', event.body);

Further Reading

On this page

No Headings