← All posts
serverless securityvibe codingAI code securityserverless functionsindie developer

How to Secure Serverless Functions in Vibe-Coded Apps

O

OverMCP Team

Quick answer

Serverless functions in vibe-coded apps often lack authentication, input validation, and error handling. To secure them, you must add proper auth checks, validate all inputs, limit function timeouts and memory, and never hardcode secrets. Start by running a free AI app security scanner to catch common misconfigurations.

What to check first

Before diving into code, audit your serverless functions with this checklist:

  • Authentication and authorization: Does your function verify the caller has permission to invoke it? Many vibe-coded apps expose endpoints without any auth.
  • Input validation: Are all parameters, headers, and body fields checked for type, length, and allowed values? AI-generated code often trusts user input blindly.
  • Secrets in environment variables: Are API keys, database URLs, or tokens stored securely (not in code or plain text in serverless config)?
  • Timeout and memory limits: Are they set appropriately? A too-high timeout can lead to cost spikes; too-low can crash the function.
  • Error handling: Does the function return generic error messages? Stack traces or internal details can leak information.
  • CORS configuration: Is it too permissive? Wildcard origins can allow any website to call your function.
  • Logging and monitoring: Are sensitive data logged? Are you alerted to unusual invocation patterns?
  • Dependencies: Are all packages up to date and free of known CVEs? Run a continuous security monitoring scan on your repo.
  • Step-by-step fix

    1. Add authentication middleware

    Most serverless platforms (Vercel, Netlify, AWS Lambda) support middleware or wrapper functions. Use a JWT verifier or API key check.

    // Example: JWT verification for Vercel serverless function (Next.js API route)
    import jwt from 'jsonwebtoken';
    
    export async function middleware(request) {
      const authHeader = request.headers.get('authorization');
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return new Response('Unauthorized', { status: 401 });
      }
      const token = authHeader.split(' ')[1];
      try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        request.user = decoded;
      } catch (err) {
        return new Response('Invalid token', { status: 401 });
      }
    }

    For public endpoints that don't need auth, ensure they are idempotent and rate-limited.

    2. Validate inputs rigorously

    Use a schema validation library like Zod or Joi to enforce types and constraints.

    import { z } from 'zod';
    
    const schema = z.object({
      email: z.string().email(),
      amount: z.number().positive().max(10000),
    });
    
    export default async function handler(req, res) {
      const result = schema.safeParse(req.body);
      if (!result.success) {
        return res.status(400).json({ error: result.error.issues });
      }
      // proceed with validated data
    }

    3. Set proper timeout and memory limits

    In your serverless configuration file (e.g., vercel.json, netlify.toml, or AWS SAM), define limits:

    // vercel.json
    {
      "functions": {
        "api/process.js": {
          "maxDuration": 10,
          "memory": 256
        }
      }
    }

    4. Never hardcode secrets

    Use environment variables or a secrets manager. In Vibe-coded apps, secrets often end up in code or config. Scan your repo with a secret leak scanner to catch any exposed keys.

    5. Add rate limiting

    Serverless functions can be invoked rapidly, leading to abuse or cost spikes. Use a rate limiter library or service.

    import rateLimit from 'express-rate-limit';
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100, // limit each IP to 100 requests per window
    });

    Common mistakes

  • No authentication at all: AI-generated serverless functions often assume they'll be called by trusted clients. Without auth, anyone can invoke them.
  • Overly permissive CORS: Using Access-Control-Allow-Origin: * allows any website to make requests, potentially leading to CSRF or data theft.
  • Logging sensitive data: AI code sometimes logs request bodies or environment variables for debugging, which can expose secrets in logs.
  • Ignoring function timeout: Default timeouts (e.g., 15 seconds on Vercel) can be too long for some tasks, leading to high costs if abused. Conversely, too short for legitimate operations.
  • Hardcoded secrets: Many vibe-coded apps store API keys directly in function code or config files, which are then committed to public repos.
  • Missing input validation: AI often assumes inputs are safe. Without validation, SQL injection, NoSQL injection, or command injection can occur.
  • Not using environment variables for configuration: Hardcoding database URLs or service endpoints makes it hard to change settings without redeploying.
  • FAQ

    How do I add authentication to a serverless function in a vibe-coded app?

    Use a middleware pattern. In Next.js API routes, create a middleware.js file that checks for a valid JWT or API key before the route handler runs. Alternatively, wrap each handler with an authentication function.

    What is the most common security flaw in vibe-coded serverless functions?

    Lack of authentication. Many AI-generated functions are designed to be called from a frontend without any token verification, making them accessible to anyone who discovers the endpoint.

    Can I use environment variables for secrets in serverless functions?

    Yes. Store secrets in your platform's environment variable settings (Vercel, Netlify, AWS). Never hardcode them in your code. Use a secrets scanner to check for any leaked keys in your repo.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free