← All posts
WebSocket securityvibe-coded appsAI coding toolsreal-time securityinsecure WebSocket

How to Fix Insecure WebSocket Connections in Vibe-Coded Apps

O

OverMCP Team

Quick answer

Insecure WebSocket connections in vibe-coded apps can expose real-time data to eavesdropping and injection attacks. To fix them, use wss:// with TLS, authenticate connections via tokens in the handshake, and validate messages server-side. This guide walks you through each step.

Why WebSocket Security Matters for Vibe-Coded Apps

When you vibe-code with tools like Cursor, Bolt.new, or Replit Agent, real-time features—chat, live notifications, collaborative editing—are often added in minutes. But AI models tend to generate WebSocket code that skips security. They focus on functionality: connecting, sending, receiving. They rarely add authentication, encryption validation, or input sanitization.

I've seen apps where the WebSocket connection uses plain ws:// over HTTP, no token verification, and messages are processed directly without checks. That's an open door for attackers.

What to Check First

Before you fix anything, run through this quick checklist:

  • [ ] Are you using wss:// (WebSocket Secure) instead of ws://?
  • [ ] Does your WebSocket handshake include a token (JWT or similar)?
  • [ ] Are messages validated and sanitized on the server?
  • [ ] Do you have a heartbeat or timeout mechanism?
  • [ ] Are origin checks enabled on the server?
  • [ ] Have you reviewed generated code for hardcoded secrets?
  • Use a free AI app security scanner to automatically detect common WebSocket vulnerabilities in your codebase.

    Step-by-Step Fix

    1. Always Use WSS (WebSocket Secure)

    Replace ws:// with wss://. On the server, ensure TLS is enabled. In Node.js with ws library:

    const https = require('https');
    const WebSocket = require('ws');
    const server = https.createServer({ cert, key });
    const wss = new WebSocket.Server({ server });

    On the client:

    const socket = new WebSocket('wss://yourserver.com');

    2. Authenticate Connections via Token

    Don't trust the URL alone. Send a token during the handshake. The most common pattern is to pass a token as a query parameter or in the subprotocol header.

    Server-side validation (Node.js ws library):

    const WebSocket = require('ws');
    const jwt = require('jsonwebtoken');
    
    const wss = new WebSocket.Server({ port: 8080 });
    
    wss.on('connection', (ws, req) => {
      const token = new URL(req.url, 'http://localhost').searchParams.get('token');
      if (!token) {
        ws.close(4001, 'Authentication required');
        return;
      }
      try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        ws.userId = decoded.userId;
      } catch (err) {
        ws.close(4001, 'Invalid token');
      }
    });

    Client-side:

    const token = 'your-jwt-token';
    const socket = new WebSocket(`wss://yourserver.com?token=${token}`);

    3. Validate and Sanitize All Messages

    Treat every message like user input—because it is. Never eval or directly execute message data. In your message handler:

    wss.on('connection', (ws) => {
      ws.on('message', (data) => {
        try {
          const parsed = JSON.parse(data);
          // Sanitize: strip HTML, limit length, check type
          if (typeof parsed.text !== 'string' || parsed.text.length > 500) {
            ws.send(JSON.stringify({ error: 'Invalid message' }));
            return;
          }
          // Process safely
        } catch (e) {
          ws.send(JSON.stringify({ error: 'Invalid JSON' }));
        }
      });
    });

    4. Implement Heartbeats and Timeouts

    AI-generated code often omits ping/pong. Without it, dead connections pile up. Add:

    function heartbeat() {
      this.isAlive = true;
    }
    
    wss.on('connection', (ws) => {
      ws.isAlive = true;
      ws.on('pong', heartbeat);
    });
    
    const interval = setInterval(() => {
      wss.clients.forEach((ws) => {
        if (ws.isAlive === false) return ws.terminate();
        ws.isAlive = false;
        ws.ping();
      });
    }, 30000);

    5. Check Origin Headers

    Restrict connections to your domain:

    const wss = new WebSocket.Server({
      verifyClient: (info) => {
        const allowedOrigins = ['https://yourapp.com'];
        return allowedOrigins.includes(info.origin);
      }
    });

    Common Mistakes

    1. Using ws:// in Production

    AI tools default to ws:// for local development. Developers forget to switch to wss:// when deploying. Without TLS, all data is sent in plaintext.

    2. No Authentication in Handshake

    Many vibe-coded apps skip token verification. They rely on the fact that the WebSocket URL is "random" or "hard to guess." Attackers can brute-force or sniff the connection.

    3. Trusting Client Input Blindly

    AI models often generate message handlers that broadcast data directly. If you don't sanitize, an attacker can send malicious payloads that inject SQL, XSS, or crash the server.

    4. Hardcoded Secrets in Client Code

    Tokens, API keys, and secret URLs often end up in client-side JavaScript. Use environment variables and never expose secrets to the client.

    5. No Rate Limiting or Connection Limits

    Without limits, an attacker can open thousands of connections and exhaust server resources. Add connection caps per user:

    const connectionsPerUser = new Map();
    
    wss.on('connection', (ws, req) => {
      const userId = ws.userId;
      const count = connectionsPerUser.get(userId) || 0;
      if (count >= 5) {
        ws.close(4002, 'Too many connections');
        return;
      }
      connectionsPerUser.set(userId, count + 1);
      ws.on('close', () => {
        connectionsPerUser.set(userId, connectionsPerUser.get(userId) - 1);
      });
    });

    How OverMCP Helps

    Instead of manually hunting for issues, you can connect your Vercel project and get a continuous security scan that catches insecure WebSocket code, leaked tokens, and missing authentication patterns before they hit production.

    FAQ

    What makes WebSocket connections insecure in vibe-coded apps?

    AI tools often generate WebSocket code without TLS, authentication, or input validation, leaving real-time features vulnerable to data theft, injection attacks, and unauthorized access.

    How do I check if my WebSocket connection is secure?

    Look at the URL: if it starts with wss://, TLS is enabled. Also verify that the server validates a token during the handshake and that all messages are sanitized.

    Can I secure an existing WebSocket without rewriting the app?

    Yes. You can add WSS by configuring TLS on your server, add token validation in the existing on('connection') handler, and insert sanitization logic in the message handler. Use a security scanner to identify all insecure spots quickly.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free