Improper Input Validation
The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.
Input validation is a frequently-used technique for checking potentially dangerous inputs in order to ensure that the inputs are safe for processing within the code, or when communicating with other components. When software does not validate input properly, an attacker is able to craft the input in a form that is not expected by the rest of the application.
Cómo corregir esta vulnerabilidad
Estrategias de prevención para Improper Input Validation basadas en 13 reglas de detección de Shoulder.
Use Pydantic models with Field validators instead of raw Request objects
- from fastapi import FastAPI, Request - - app = FastAPI() - - @app.post("/users") - async def create_user(request: Request): - data = await request.json() - return {"user": data["username"]} + from fastapi import FastAPI + from pydantic import BaseModel, EmailStr, Field + + app = FastAPI() + + class UserCreate(BaseModel): + username: str = Field(min_length=3, max_length=50) + email: EmailStr + + @app.post("/users") + async def create_user(user: UserCreate): + return {"user": user.username}
Validate business-critical inputs with range constraints using Pydantic or manual checks
- from flask import request - - @app.route('/apply-discount', methods=['POST']) - def apply_discount_route(): - discount = float(request.form['discount']) - apply_discount(discount) + from pydantic import BaseModel, Field + from fastapi import FastAPI + + class DiscountRequest(BaseModel): + discount: float = Field(..., ge=0, le=100) + quantity: int = Field(..., gt=0) + + @app.post('/apply-discount') + async def apply_discount_route(req: DiscountRequest): + apply_discount(req.discount) return {'status': 'applied'}
Parse string inputs to typed values and validate against business rules before use
package main - import "net/http" - - func applyDiscount(w http.ResponseWriter, r *http.Request) { - discount := r.FormValue("discount") - // discount is a raw string, used without parsing or validation + import ( + "net/http" + "strconv" + ) + + func applyDiscount(w http.ResponseWriter, r *http.Request) { + discountStr := r.FormValue("discount") + discount, err := strconv.ParseFloat(discountStr, 64) + if err != nil { + http.Error(w, "Invalid discount format", http.StatusBadRequest) + return + } + if discount < 0 || discount > 100 { + http.Error(w, "Discount must be between 0 and 100", http.StatusBadRequest) + return + } total := price * (1 - discount/100) processOrder(total) }
Use Echo struct binding with validation tags instead of untyped maps
package main import "github.com/labstack/echo/v4" - func handler(c echo.Context) error { - var input map[string]interface{} - c.Bind(&input) - name := input["name"].(string) - return c.String(200, name) + type UserInput struct { + Name string `json:"name" validate:"required,min=2"` + Email string `json:"email" validate:"required,email"` + } + + func handler(c echo.Context) error { + var input UserInput + if err := c.Bind(&input); err != nil { + return c.JSON(400, map[string]string{"error": err.Error()}) + } + if err := c.Validate(&input); err != nil { + return c.JSON(400, map[string]string{"error": err.Error()}) + } + return c.String(200, input.Name) }
Use Fiber BodyParser with typed structs and validation tags
package main - import "github.com/gofiber/fiber/v2" - - func handler(c *fiber.Ctx) error { - var input map[string]interface{} - c.BodyParser(&input) - name := input["name"].(string) - return c.SendString(name) + import ( + "github.com/gofiber/fiber/v2" + "github.com/go-playground/validator/v10" + ) + + var validate = validator.New() + + type UserInput struct { + Name string `json:"name" validate:"required,min=2"` + Email string `json:"email" validate:"required,email"` + } + + func handler(c *fiber.Ctx) error { + var input UserInput + if err := c.BodyParser(&input); err != nil { + return c.Status(400).JSON(fiber.Map{"error": err.Error()}) + } + if err := validate.Struct(&input); err != nil { + return c.Status(400).JSON(fiber.Map{"error": err.Error()}) + } + return c.SendString(input.Name) }
Validate business-critical inputs with range checks before processing
app.post('/apply-discount', (req, res) => { - const discount = req.body.discount; - applyDiscount(discount); + const value = parseFloat(req.body.discount); + if (isNaN(value) || value < 0 || value > 100) { + return res.status(400).json({ error: 'Discount must be 0-100' }); + } + applyDiscount(value); });
Use server-side prices from the database and validate ranges for business-critical values
app.post('/api/orders', (req, res) => { - const { productId, quantity, price } = req.body; - const total = price * quantity; + const { productId, quantity } = req.body; + const product = products.get(productId); + if (!product) return res.status(404).json({ error: 'Product not found' }); + const total = product.price * quantity; orders.push({ total }); });
Add class-validator decorators to all DTO properties and enable the global ValidationPipe
- export class CreateUserDTO { - username: string; - email: string; - age: number; - } - - @Controller('users') - export class UserController { - @Post() - create(@Body() dto: CreateUserDTO) { - return this.userService.create(dto); - } - } + import { IsString, IsEmail, IsInt, Min, Max, MinLength } from 'class-validator'; + + export class CreateUserDTO { + @IsString() + @MinLength(3) + username: string; + + @IsEmail() + email: string; + + @IsInt() + @Min(0) + @Max(150) + age: number; + } + + // In main.ts: app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
Encuentra vulnerabilidades en tu código
Usa Shoulder para escanear tu código en busca de patrones Improper Input Validation. 13 reglas.
# Scan with Shoulder CLI npx @shoulderdev/cli trust --cwe=20 # Or scan entire project npx @shoulderdev/cli trust .
Reglas de Detección (13)
Qué buscar en las revisiones de código
Estos patrones indican vulnerabilidades potenciales de Improper Input Validation. Búscalos durante las revisiones de código y auditorías de seguridad.
Escanea tu base de código para Improper Input Validation
Shoulder CLI encuentra patrones vulnerables en toda tu base de código.