Vibe coding security: what can go wrong and how to stop it
Oct 27, 2026
Vibe coding security problems usually come from three things an AI assistant does quickly: installing packages nobody checked, putting secrets in code, and writing Docker files nobody reads. Attackers use all three, and a worm can copy itself from one developer machine to the next through stolen tokens. A password vault, fewer admin rights, and change monitoring limit how far a bad install can go.
You're talking out loud to Claude Code. “Add Stripe checkout, connect the database, ship it.” Three minutes later the app runs, and you haven't opened a single file.
That speed is why people love vibe coding. It's also where vibe coding security risks start. While you were talking, the AI picked packages, wrote passwords into files, and built a Docker image. You said yes to all of it without reading.
The AI works with your permissions and nobody checks its work
When you use an AI coding tool, it runs commands as you. It can install packages, read your files, edit your config, and use your cloud login. Normal code gets a review before it ships. Vibe-coded code often skips that step, because the app works and nothing feels wrong.
Some people also remove the last safety net. Claude Code has a flag that skips every permission prompt:
# Skips every permission prompt. Every command the agent picks now runs.
claude --dangerously-skip-permissions
On a throwaway sandbox, that's fine. On a work laptop full of tokens and keys, it's a real risk.
Fake packages, and the worm that spreads through real ones
AI assistants sometimes suggest packages that don't exist. Attackers watch for those made-up names, register them, and wait for someone to run the install. The name for this is slopsquatting. Here's a dependency list that looks fine at a glance:
{
"name": "my-saas-app",
"dependencies": {
"express": "^4.19.2",
"stripe": "^16.0.0",
"react-auth-helper-pro": "^1.0.3"
},
"scripts": {
"postinstall": "node scripts/setup.js"
}
}
You know the first two. The third sounds reasonable, but nobody on your team picked it. The postinstall line runs by itself the moment you install, with your permissions. Before you accept a new package, open its page and check when it was published, how many people download it, and whether it links to a real repository. A package that appeared last week with a handful of downloads deserves a second look.
Now add the worm. In September 2025, a worm called Shai-Hulud spread through npm. It ran when a package was installed, stole tokens and cloud keys from the developer's machine, and used those tokens to publish infected versions of the victim's own packages. Everyone who installed those packages got the same treatment.
A vibe-coded laptop is an easy target for something like that. Tokens sit in plain files, the user has local admin rights, and installs get approved without a glance.
Secrets end up in your code
Ask an assistant to “connect to Stripe and Postgres” and you'll often get this:
// config.js
export const config = {
stripeKey: "sk_live_EXAMPLE_do_not_use",
databaseUrl: "postgres://admin:Summer2024!@prod-db.example.com:5432/app",
jwtSecret: "supersecret"
};
It works, so you move on. Then comes the first commit:
$ git add .
$ git commit -m "initial commit"
# No .gitignore, so .env went along too
Git remembers everything. If a key lands in a commit and you delete the file later, it's still in the history. Bots scan public repositories for keys all the time, so a leaked key can be in use before you notice. If you already pushed one, treat it as stolen and rotate it. Secrets also leak when you paste them into a prompt, since they end up in the agent's context and logs.
Stolen secrets are what the worm above runs on. A token in a leaked file is a way to publish packages under your name. If you're not sure where sensitive data already sits in your company, sensitive data discovery is a good place to start.
Docker files that build fine and leak anyway
Ask for a Dockerfile and you'll get one that builds. For most people, that's the only test.
FROM node:latest
WORKDIR /app
COPY . .
ENV STRIPE_KEY=sk_live_EXAMPLE_do_not_use
RUN npm install
EXPOSE 3000 9229
CMD ["node", "server.js"]
Five problems sit in those seven lines. The latest tag changes without warning, so tomorrow's build can differ from today's. COPY . . pulls your .env file and .git folder into the image. The ENV line writes the secret into the image layers, where anyone who can pull the image can read it. The container runs as root. And port 9229 opens the Node.js debugger to the network.
Here's a version you can ship without wincing:
FROM node:20.17-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --ignore-scripts
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]
Add a .dockerignore file with .env, .git, and node_modules in it, and pass the Stripe key when the container starts, from a vault or secrets manager.
The vibe coding threat model in plain words
Three things sit together on every vibe-coded project: the agent has your permissions, nobody reviews the code, and nobody checks the dependencies. Each one is a small risk alone. Side by side they chain. One leaked token becomes a published package under your name, and that package becomes the worm's next stop. Security people call this a threat model. You can think of it as a list of the ways someone could get in and what they could reach once they do.
Vibe coding guardrails you can set up today
You can keep vibe coding. Add a few checks that don't depend on anyone reading every line.
Problem | What to do | Example |
|---|---|---|
|
Unchecked packages |
Read every new dependency before installing, commit your lockfile, and turn off install scripts by default |
|
|
Secrets in code |
Keep secrets in a vault, load them at startup, and ignore .env before the first commit |
|
|
Risky Docker files |
Pin the image version, run as a non-root user, and exclude .env and .git |
|
|
Too many permissions |
Work as a standard user and keep permission prompts on |
Skip |
|
Changes nobody approved |
Watch files and configs after deploy and flag anything unexpected |
File integrity monitoring |
You can also give the agent standing rules. Claude Code reads a CLAUDE.md file in your project, so put your guardrails there:
# CLAUDE.md
- Never put secrets, keys, or passwords in code. Read them from environment variables.
- Ask me before adding any new dependency, and tell me why it's needed.
- Never use the latest tag for Docker base images. Run containers as a non-root user.
The agent can still get it wrong, so keep checking the diff. The rules just cut down how often you have to catch something.
How Netwrix helps
Netwrix Password Secure gives your credentials a place to live that isn't config.js. It's an encrypted vault with role-based access and a full record of who used which password, and applications can pull credentials at runtime through the SDK.
Netwrix Change Tracker watches containers, servers, and endpoints with file integrity monitoring and compares every change against what was approved. Say a package edits a system file at 2 a.m. or a container drifts from its baseline. Change Tracker flags it, and your team sees it the same day.
See Netwrix Change Tracker in action.
Learn moreVibe coding security FAQs
Share on
Learn More
About the author
Dan Piazza
Manager of Product Management
Dan Piazza is a Manager of Product Management at Netwrix, responsible for multiple Endpoint, DSPM, and Directory products. He has worked in technical roles since 2013, with a passion for cybersecurity, data protection, automation, and code. Prior to Product Management, he's worked in Systems Engineering, Quality Assurance, and Technical Support.