Security

How to Check If Your Vibe Coded App Is Secure

8 min read By Red Corner

You asked the model whether your app is secure. It said yes, and you moved on. If you are wondering how to check if a vibe coded app is secure, the uncomfortable answer is that the model’s opinion of its own work is not a check at all.

A builder finishing a mobile game asked a forum whether they could trust Claude or Codex to scan for security holes, or whether a human review was unavoidable. A security professional with two decades of breaking apps for a living asked the same community what people were actually doing: manual review, a scanner, trusting the model to self-audit, or shipping and hoping. The thread produced very few concrete answers.

What this problem looks like

The pattern in builder forums has three shapes. The first is the self-certified app. The builder prompts “make this production ready and secure”, the agent adds some input validation and a comment about best practices, and that gets treated as an audit. One commenter joked about adding “and I really mean it” to their config file. Another was blunter: the model will confidently reassure you, and if you cannot tell the difference you will be happy right up until you find out the hard way.

The second is the invisible leak. Someone who audits AI-built codebases described a web app that fetched a full configuration record from the database and handed it straight to a client-side component. Every page rendered, and the whole config, secrets included, sat in the HTML source for anyone to read. No click-around-and-see-if-it-works loop would ever surface that.

The third is the runtime attack nobody prompted for. Your agent calls a tool, the content that comes back contains instructions, and the agent follows them. That is prompt injection arriving through a web page, a document or an API response rather than the chat box. As one commenter noted, no amount of security-aware prompting stops it, because it happens in the running environment. Add the dependency pile: another commenter observed that agents are poor at dependency management, pulling in old or known-vulnerable libraries, and that the first vulnerability scan on an agent-built project tends to be an unpleasant surprise.

Why security goes unchecked when you vibe code

None of this happens because AI writes uniquely bad code; humans write injection bugs too. The difference is structural. Conventional application security is built on the premise that the person shipping the code understands it, and on a static analyzer (a tool that reads source and flags dangerous patterns before anything runs), a reviewer who is not the author, and a test before deploy. Vibe coding removes all of that at once. The author is a model, the reviewer is the same model, and the test is “I clicked around and it worked.”

There is also a quirk in how these models behave. They are far better at reviewing code than writing it, as long as the code is presented as someone else’s. Ask the model that just wrote a function whether it is secure and it tends to defend its own work; ask a fresh session to hunt for flaws in an unfamiliar file and it finds them. One commenter’s theory is that models have seen far more code annotated with what not to do than examples of doing it right, so they recognize mistakes better than they avoid them.

And even a good review only looks at source, not at what your app does when running with real permissions and real attacker input. The cost of that gap is real: a leaked config hands over your third-party accounts, an endpoint that trusts the UI lets one user read another’s data (which may carry legal obligations worth a lawyer’s time), and a prompt-injected agent can act on your behalf without permission.

How to run a vibe coding security audit today

Treat this as a vibe coding security checklist, run in order, starting from the assumption that the code contains flaws and your job is to prove otherwise.

Step 1: Get a fresh model to review the code, not the one that wrote it

In Claude Code, open a new session or sub-agent with no memory of the build and give it a reviewer role: “You are a security reviewer who did not write this code. Audit it for the OWASP Top 10 (the standard list of the most common web vulnerabilities), authorization on every endpoint, secrets reaching the client, and unsafe handling of user input. Report file, line, severity and a proposed fix. Do not fix anything yet.” Cursor, Lovable and Replit have equivalents. If you can, run the same prompt through a second model and compare lists; one commenter loops two models, one fixing and one hunting, until the hunter comes up empty. Then add a rule to your CLAUDE.md that every new endpoint gets a separate-context review before commit.

Step 2: Run a static scanner and a dependency scanner

Model review is a reasoning pass; a scanner is a pattern pass; they catch different things. Ask Claude Code to install and run a static analysis tool for your stack (Semgrep is a common open-source choice) and your package manager’s audit command for known-vulnerable dependencies, then explain and rank each finding in plain English. Commit first, and make it show you every diff rather than silently upgrading or suppressing.

Step 3: Attack the running app

With the app running locally, have Claude Code write a small set of adversarial tests: log in as user A and request user B’s records by changing an ID in the URL; submit fields containing quotes, angle brackets and script tags; hammer the login and password reset endpoints to see whether anything throttles you; search the source of every authenticated page for anything resembling a key or token, which is where the config leak above lived. For more, see how to test a vibe coded app.

Step 4: Audit your agent’s tool calls for prompt injection

If your product has an LLM that reads external content and can take actions, you have a prompt injection surface. Have your reviewer session trace every path where untrusted text enters the model and every tool it can invoke. Then apply three controls: treat fetched content as data, never as instructions; require user confirmation before any irreversible or outbound action; and give the agent the narrowest permissions it needs. Test by planting an instruction in a document the agent will read and confirming it ignores it.

Step 5: Fix the basics, then re-run everything

The three misses one commenter sees most: secrets in the frontend, backend endpoints that trust the UI, and no abuse controls like rate limiting. See exposed API keys and UI-only security for each. Once fixed, run steps 1 through 4 again, because fixes open new holes. If you handle payments or sensitive data, a short fixed-scope engagement with a penetration tester (someone paid to break in) is the final check; one commenter who does this work described it as a small flat-rate job.

How a Red Corner CTO would have prevented this problem

Before the first prompt, a Red Corner CTO would have asked one question: what does this app hold that someone would want to steal or abuse? The answer sets the security bar for the project and gets written into the CLAUDE.md before any feature does, alongside rules that no secret reaches client code, every endpoint checks authorization on the server, and any AI feature treats external content as untrusted.

In week one, the CTO would have insisted on scaffolding the safety net before the landing page: a static scanner wired into the repo, dependency auditing on every install, and a fresh-context review pass after any endpoint work. It means the AI’s mistakes get flagged the moment they land instead of months later.

During the build, the CTO would have read the first few pull requests personally and caught the config object being handed wholesale to a client component, the kind of thing an experienced eye spots in seconds and a click-through never will. They would have asked to see the adversarial tests, not just the passing ones, and if the product had an agent with tools, drawn the trust boundary on a whiteboard: where untrusted text enters, every action the model can take, and the confirmation gate between them.

Before launch, the CTO would have run the full checklist with the builder watching, so the builder learns to run it themselves, and decided with them whether the data at stake justified an external penetration test. Before payments were switched on, they would have asked whether the builder understood what they might be on the hook for if user data leaked, and pointed them at a lawyer if the answer was fuzzy.

After launch, the CTO would have set up dependency alerts, a re-review cadence, and a plain rule: no new integration ships without the same review the original code got.

Frequently asked questions

Can I trust Claude Code to audit its own security?

Not in the same session that wrote the code. Models find vulnerabilities well in code they treat as someone else’s and poorly in their own recent output. Use a fresh session or sub-agent with a reviewer role, and back it with a scanner and runtime tests.

What is prompt injection in a vibe coded app?

It is when text your AI feature reads, such as a web page or an API response, contains instructions and the model follows them as if they came from you. A stricter system prompt cannot fix it because the attack arrives at runtime through the content. Treat fetched content as data, limit the agent’s permissions, and require confirmation for consequential actions.

Do I need a penetration test for a small vibe coded SaaS?

It depends on what you hold. If you store payment details or personal data, or let an agent act for users, a short fixed-scope assessment before launch is worth it. For a low-stakes tool, the scanner, fresh review and adversarial tests above may be enough, as long as you actually run them.

Get a CTO in your corner

Vibe coding is a legitimate way to build. What it lacks is an experienced pair of eyes that knows which of the model’s confident answers to distrust. Red Corner puts real CTOs in your Slack and your code reviews, so the security check happens before launch instead of after the breach. Visit redcorner.io to get a CTO in your corner.

Talk to your CTO before you commit to anything.

Every member starts with a call. We make sure we can help you, and that you are ready for the help.

Request a call with your CTO

Every member starts with a call. No card.