← All posts
API securityvibe codingAI-built appsNext.jssecurity fix

Fix Insecure API Routes in AI-Built Apps: A Step-by-Step Guide

O

OverMCP Team

Quick answer

Insecure API routes in AI-built apps often lack authentication checks, have no input validation, and expose sensitive data. Fix them by adding middleware for auth, validating all inputs, and restricting HTTP methods. Use a security scanner to catch these issues before deployment.

What to check first

Before diving into fixes, run this checklist on every API route:

  • [ ] Does the route have authentication middleware? (e.g., requireAuth)
  • [ ] Are inputs validated using a library like zod or joi?
  • [ ] Is the HTTP method restricted (GET, POST, etc.)?
  • [ ] Are error messages generic (no stack traces)?
  • [ ] Is sensitive data filtered from responses?
  • [ ] Is rate limiting applied?
  • [ ] Are CORS headers properly configured?
  • [ ] Have you scanned for leaked secrets in the code?
  • If most boxes are unchecked, your API routes are likely insecure. AI coding tools like Cursor or Bolt.new often generate minimal routes that skip these checks.

    Step-by-step fix

    1. Add authentication middleware

    Most AI-generated routes miss authentication. Add a middleware that verifies tokens or session cookies.

    // middleware/auth.js
    import jwt from 'jsonwebtoken';
    
    export function requireAuth(req, res, next) {
      const token = req.headers.authorization?.split(' ')[1];
      if (!token) return res.status(401).json({ error: 'Unauthorized' });
    
      try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        req.user = decoded;
        next();
      } catch (err) {
        return res.status(401).json({ error: 'Invalid token' });
      }
    }

    2. Validate all inputs

    AI code often trusts user input. Use a schema validator to enforce types and constraints.

    import { z } from 'zod';
    
    const createUserSchema = z.object({
      email: z.string().email(),
      name: z.string().min(2).max(50),
      age: z.number().int().positive().optional(),
    });
    
    // In your route handler
    const parsed = createUserSchema.safeParse(req.body);
    if (!parsed.success) {
      return res.status(400).json({ error: parsed.error.flatten() });
    }

    3. Restrict HTTP methods

    Ensure routes only accept expected methods. This prevents unintended operations.

    // In your route definition (Next.js App Router example)
    export async function POST(req) {
      // Only POST allowed
    }
    
    export async function GET(req) {
      return new Response('Method not allowed', { status: 405 });
    }

    For Express-like frameworks, use method check:

    app.post('/api/users', (req, res) => { /* ... */ });
    app.all('/api/users', (req, res) => res.status(405).end());

    4. Sanitize error messages

    Don't leak stack traces or internal details. Always return generic errors.

    try {
      // risky operation
    } catch (err) {
      console.error(err); // log internally
      res.status(500).json({ error: 'Internal server error' });
    }

    5. Filter sensitive data from responses

    Use a serialization library or manual mapping to exclude fields like passwords.

    function sanitizeUser(user) {
      const { password, apiKey, ...safeUser } = user;
      return safeUser;
    }

    6. Add rate limiting

    Prevent abuse with a simple rate limiter.

    import rateLimit from 'express-rate-limit';
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 100, // limit each IP to 100 requests per windowMs
      message: 'Too many requests, please try again later.'
    });
    
    app.use('/api/', limiter);

    7. Configure CORS properly

    Don't use Access-Control-Allow-Origin: * in production. Restrict to your domain.

    import cors from 'cors';
    
    app.use(cors({
      origin: 'https://yourapp.com',
      methods: ['GET', 'POST'],
      credentials: true,
    }));

    8. Scan for leaked secrets

    Use a secret leak scanner to find hardcoded API keys or tokens in your codebase before deploying.

    Common mistakes

  • No authentication at all: AI-generated endpoints often expose CRUD operations without any auth check.
  • Trusting user input directly: Many apps skip validation, leading to injection attacks.
  • Overly permissive CORS: Using wildcard origins allows any site to call your API.
  • Exposing internal error details: Stack traces in responses help attackers.
  • Forgetting rate limiting: Without it, your API is vulnerable to brute force and DDoS.
  • Hardcoded secrets: AI tools sometimes embed API keys in code—always use environment variables.
  • How to prevent these issues in future AI coding sessions

  • Use a consistent API route template that includes auth, validation, and error handling.
  • Prompt the AI explicitly: "Add authentication and input validation using zod to this route."
  • Run a [free AI app security scanner](https://www.overmcp.com/) after each coding session to catch vulnerabilities early.
  • Set up [continuous security monitoring](https://www.overmcp.com/monitor) to alert you when new issues appear.
  • FAQ

    What is an insecure API route?

    An API route that lacks authentication, input validation, or proper error handling, making it vulnerable to unauthorized access, injection, or data leaks.

    How do I know if my API routes are insecure?

    Run a security scan or manually check for missing auth, validation, and exposed secrets. Tools like OverMCP's security headers checker can help.

    Can AI coding tools generate secure API routes?

    Yes, if you prompt them correctly. Always include security requirements in your prompts and review the generated code for common mistakes.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free