← All posts
dependency confusionvibe codingAI code securitynpm securitysupply chain attack

Dependency Confusion Prevention for Vibe-Coded Apps: A Practical Guide

O

OverMCP Team

Quick answer

Dependency confusion prevention in vibe-coded apps starts with locking down your package manager and verifying every dependency. Use a lockfile, pin exact versions, and configure your registry to block private package names from public sources. For AI-generated code, run a secret leak scanner and audit your dependencies before deploying.

What is dependency confusion?

Dependency confusion (also called package substitution) happens when an attacker publishes a malicious package to a public registry with the same name as a private package used in your app. Your package manager, if misconfigured, might pull the public malicious version instead of your private one. This can lead to code execution, data theft, or full app compromise.

For vibe-coded apps, this risk is higher because AI coding tools often generate package names on the fly and may not follow your internal naming conventions. You might not even realize you have a private package dependency.

Why vibe-coded apps are particularly vulnerable

AI coding tools like Cursor, Bolt.new, and Replit Agent are brilliant at generating code quickly, but they don't always follow security best practices. They might:

  • Use generic package names that collide with public ones
  • Forget to add dependencies to a lockfile
  • Pull from multiple registries without specifying which one
  • Not validate the integrity of packages
  • Because you're moving fast, you might not inspect every generated package.json line. That's exactly what an attacker counts on.

    What to check first

    Before you do anything else, run this checklist to assess your exposure:

  • [ ] Look for any package.json in your project root and in every subdirectory (AI tools sometimes create multiple).
  • [ ] Check if you have a lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml). If not, you're at risk.
  • [ ] Search for any dependency names that look generic or suspiciously similar to common packages (e.g., helper, utils, logger).
  • [ ] Verify that your private packages (if any) use a unique scope like @mycompany/ and are not published publicly.
  • [ ] Review your npm/yarn/pnpm config for custom registries or registry settings.
  • [ ] Run npm audit (or equivalent) to see known vulnerabilities, but remember this won't catch dependency confusion.
  • [ ] Use a security headers checker and a SSL certificate checker to ensure your app's basic security posture is sound.
  • If any of these fail, proceed to the fix below.

    Step-by-step fix

    1. Create and commit a lockfile

    If you don't have a lockfile, generate one now:

    # For npm
    npm install --package-lock-only
    
    # For yarn
    yarn install --mode=skip-build
    
    # For pnpm
    pnpm install --lockfile-only

    Commit this lockfile to your repository. It ensures that every install uses the exact same versions, preventing substitution.

    2. Pin exact versions

    In your package.json, use exact versions (no ^ or ~) for all dependencies. This prevents a minor update from pulling in a malicious version.

    {
      "dependencies": {
        "express": "4.19.2",
        "lodash": "4.17.21"
      }
    }

    3. Scope your private packages

    If you have any private packages, give them a unique scope (e.g., @mycompany/). This makes it impossible for a public package with the same unscoped name to be substituted.

    4. Configure your registry to block public packages with private names

    For npm, you can use overrides in your package.json to force specific packages to resolve from a specific registry. Here's an example:

    {
      "overrides": {
        "@mycompany/private-pkg": {
          "registry": "https://npm.pkg.github.com"
        }
      }
    }

    Alternatively, use .npmrc to set the registry for your private scope:

    @mycompany:registry=https://npm.pkg.github.com

    5. Scan your dependency tree for suspicious packages

    Use npm ls to list your dependency tree and check for any unexpected packages. You can also write a quick script to compare your dependencies against a list of known malicious packages (though that's not foolproof).

    6. Use a security scanner

    Run a comprehensive security scan that includes dependency checks. OverMCP's free AI app security scanner can help you identify vulnerabilities in your vibe-coded app, including dependency-related risks. It also checks for leaked secrets and misconfigurations.

    7. Monitor continuously

    Dependency confusion attacks can happen anytime. Set up continuous security monitoring to get alerts when new vulnerabilities are detected in your dependencies.

    Common mistakes

    Mistake 1: Not using a lockfile

    Many AI-generated projects skip the lockfile, assuming it's unnecessary. Without it, your app is vulnerable to dependency confusion every time you run npm install.

    Mistake 2: Using generic package names

    If your AI tool generates a package name like utils or helpers, an attacker might have already published a malicious version. Always rename to something unique.

    Mistake 3: Ignoring the `.npmrc` file

    If you have multiple registries (e.g., public npm and GitHub Packages), forgetting to configure .npmrc can cause your private packages to be fetched from the public registry.

    Mistake 4: Not auditing AI-generated code

    Vibe-coded apps often include dependencies that you didn't write. You must review every dependency added by the AI, not just trust it.

    Mistake 5: Assuming `npm audit` catches everything

    npm audit only checks for known vulnerabilities, not for dependency confusion. It's a good start but not sufficient.

    How to integrate this into your vibe-coding workflow

  • Before you start coding: Set up your project with a lockfile and .npmrc from the beginning. If you're using a template, ensure it includes these.
  • During coding: Whenever the AI adds a new dependency, stop and review it. Check the package name, version, and whether it's scoped.
  • Before deployment: Run a full security scan, including dependency checks, secret scanning, and header checks.
  • After deployment: Enable continuous monitoring so you're alerted to any new vulnerabilities.
  • By making these steps part of your routine, you reduce the risk without slowing down your shipping speed.

    Why OverMCP is your ally

    OverMCP is built specifically for vibe-coded apps. It scans your project for security issues, including dependency risks, leaked secrets, and misconfigurations. It integrates with your workflow, so you can catch problems early. Instead of spending hours manually auditing, you can automate the process and focus on building.

    FAQ

    Can dependency confusion happen with public packages only?

    No, dependency confusion can also occur if you have a private package that is not scoped and has the same name as a public package. Attackers can publish a malicious version to the public registry, and your package manager might fetch it if your configuration is not locked down.

    How do I know if my app is already compromised?

    Look for signs like unexpected network requests, strange behavior, or new dependencies in your lockfile. Run a full security scan and check your production logs for anomalies. If you suspect compromise, rotate all secrets and consider redeploying from a clean environment.

    What is the best way to prevent dependency confusion in AI-generated code?

    The best way is to use a combination of lockfiles, exact version pinning, scoped private packages, and registry configuration. Additionally, regularly scan your dependencies with a tool like OverMCP, which can identify suspicious packages and other vulnerabilities.

    ---

    Protect your vibe-coded app from dependency confusion and other threats. Start with a [free scan](https://www.overmcp.com/) today.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free