Product
Scanner Reports AI Integration
Resources
Guides Research Security checklist Docs Status
Account
Sign in Scan your app free
Guides/Security guide
Security guide

The vibe-coder's security checklist

What the research actually says about AI-generated code — and the fourteen checks worth running before real users arrive.

You built it in a weekend.

The login works. The database is connected. Payments go through. The dashboard looks good. You asked an AI coding agent to fix the bugs, deployed the application, clicked around for ten minutes and nothing immediately broke.

That does not mean the application is secure.

The rapid rise of tools such as Cursor, Claude Code, Codex, Replit, Lovable, Bolt and other AI-assisted development platforms has radically lowered the barrier to building software. Someone who previously needed a developer can now describe an application in natural language and have much of the architecture, frontend, backend and database integration produced automatically.

That is enormously useful. It also creates a peculiar security problem.

AI coding systems are extremely good at completing the task they have been given. Security requirements, however, are often the requirements nobody explicitly mentions.

A user asks:

“Let users edit their profile.”

The coding agent builds the profile editor.

The user usually does not also say:

“Make sure the server verifies that the authenticated user actually owns the profile being edited, reject privileged fields supplied from the browser, enforce the same rule at the database layer, validate every field server-side and make sure another user cannot simply change the profile ID in the request.”

Yet those invisible requirements are precisely what separate a working application from a secure one.

And increasingly, research is showing that this distinction matters.

What the strongest research has actually found

There are plenty of dramatic statistics circulating about vibe-coded security. Some are real. Some have been stripped of their methodology. Others appear to have been repeated between blogs until they became accepted as fact.

The clearest evidence so far comes from several different types of research: large studies of real deployed applications, controlled coding-agent experiments, vulnerability benchmarks and security-company investigations.

They do not all measure the same thing, so their percentages should not be mixed together. But taken together, they point in remarkably similar directions.

90% of 200 audited vibe-coded applications contained a validated vulnerability

One of the most substantial studies so far is the 2026 paper Understanding the (In)Security of Vibe-Coded Applications, by researchers Junquan Deng, Zhiyu Fan and Ruijie Meng.

The researchers assembled 10,517 real-world vibe-coded applications. They identified publicly reachable deployments and randomly selected 200 deployed web applications for detailed security auditing.

Rather than simply counting whatever an automated scanner reported, the researchers used multiple AI-assisted auditing configurations, deduplicated the candidate findings, analysed exploitability and subjected findings to independent human review.

The final dataset contained 1,471 validated vulnerabilities.

Of the 200 applications examined, 180 — 90% — contained at least one validated vulnerability. Among vulnerable applications, the median was seven vulnerabilities. The researchers classified 20% of the final findings as Critical and 56.7% as High, meaning 76.7% of the validated vulnerabilities were classified High or Critical.1

Those numbers are not an Epherem benchmark. They come directly from independent academic research.

More interesting than the headline percentage, however, is where the vulnerabilities appeared.

Broken Access Control accounted for 36.0% of the validated findings. Cryptographic Failures accounted for 20.7%, while Injection accounted for 17.7%.

Together, those three categories represented 74.4% of all vulnerabilities found in the study.1

That immediately tells us something important about how a vibe-coder security checklist should be prioritised.

The largest risks are not primarily cosmetic hardening issues.

They are trust-boundary failures:

  • Who can access this object?
  • Who can change this record?
  • Which credentials can the browser obtain?
  • What happens when attacker-controlled data reaches a sensitive operation?
  • Does the server actually enforce the rules the interface appears to enforce?

Those questions matter much more than whether an application happens to be missing a particular HTTP header.

The most important finding may be why the vulnerabilities happened

The 2026 study also investigated the causes of the vulnerabilities it found.

The researchers identified recurring failure patterns including placeholder logic, insufficiently filtered input, secret exposure, forgotten security requirements and security mechanisms that were applied to one part of an application but not another.1

This is particularly relevant to vibe coding because AI systems often optimise locally.

Imagine an application has ten API routes.

Nine use an authentication middleware.

A new feature is requested and the AI creates route number ten.

The new route works perfectly.

But the agent fails to apply the authentication mechanism used by the previous nine routes.

Nothing crashes. There may be no visible warning. The feature passes ordinary functional testing.

The security boundary has simply disappeared.

This class of failure is easy for a non-technical builder to miss because the application behaves exactly as expected when used normally.

Attackers do not use applications normally.

The security checklist

There is no single list, of any length, capable of representing every vulnerability an application might contain.

But for someone building a typical modern AI-generated web application, the following checks cover some of the highest-value areas to investigate before real users and real data enter the system.

The evidence suggests starting with authorization, credentials and attacker-controlled input, then moving outward into defensive configuration and operational hardening.

1. Never expose privileged secrets to the client

One of the easiest catastrophic mistakes is also one of the easiest to detect: placing a genuinely privileged credential somewhere the browser can obtain it.

This could include:

  • database credentials;
  • OpenAI or other paid API secrets;
  • Stripe secret keys;
  • private JWT signing secrets;
  • administrative tokens;
  • backend service credentials;
  • Supabase service_role or secret keys.

But there is an important nuance.

Not every API key visible in frontend code is actually secret.

Supabase illustrates this perfectly.

Supabase currently distinguishes between low-privilege publishable keys and elevated secret keys. Its documentation explicitly states that sb_publishable_... keys are safe to expose in webpages and other public components. Legacy anon keys serve a similar purpose.

By contrast, sb_secret_... keys and legacy service_role credentials are intended for trusted backend environments. Supabase states that these elevated credentials provide broad project access and bypass Row Level Security.7

That means a security scanner should not blindly report:

“Supabase key found in JavaScript — Critical.”

It must first determine what type of credential it is.

The distinction is enormous:

Publishable key in browserexpected.
Service-role credential in browserpotentially catastrophic.

Supabase itself warns never to place secret keys in webpages, public source code, URLs or browser environments. It also states that its elevated service role uses PostgreSQL's BYPASSRLS capability, skipping attached Row Level Security policies.7

If a privileged credential has already been exposed, deleting it from the source code is not enough.

Assume it may have been copied.

Rotate or revoke it.

2. Treat .env as storage, not protection

Environment files are frequently misunderstood.

Putting a secret inside .env does not magically make it secure.

A .env file is simply a convenient way of supplying configuration values to an application. If it is committed into a public repository, placed beneath a publicly served directory or accidentally bundled into client-side code, its contents may still be exposed.

For server-side secrets:

  • exclude local environment files from source control where appropriate;
  • use the deployment platform's secret/environment management;
  • make sure sensitive variables are not exposed through client-side environment prefixes;
  • inspect generated bundles for accidental secrets;
  • rotate anything that has already been leaked.

And again, classification matters.

A public application identifier sitting in .env is not automatically a vulnerability simply because it lives in an environment file.

The question is always:

What does this value allow an attacker to do if they obtain it?

That question produces far better findings than simply flagging every variable containing words such as KEY, TOKEN or SECRET.

3. Protect the database itself: RLS and data authorization

For applications built with Supabase, Row Level Security deserves special attention.

Supabase describes RLS as granular authorization enforced directly inside PostgreSQL. Its current documentation warns that a table in an exposed schema without RLS can be readable or writable by roles that have corresponding grants, and recommends enabling RLS on exposed tables.8

A typical policy might conceptually enforce:

A user may access this row only when the row's user_id matches the authenticated user's ID.

This is powerful because authorization is enforced at the data layer instead of relying entirely on application code.

But simply asking:

“Is RLS enabled?”

is not enough.

A useful security review should ask:

  • Which tables are exposed?
  • Is RLS enabled on those tables?
  • Which operations are granted to anon?
  • Which operations are granted to authenticated?
  • What policies apply to SELECT?
  • What policies apply to INSERT?
  • What policies apply to UPDATE?
  • What policies apply to DELETE?
  • Do those policies actually restrict rows by the correct user or tenant?
  • Is privileged backend code bypassing RLS?
  • Are storage objects protected appropriately?

Supabase explains that grants determine whether a role may perform an operation at all, while RLS policies determine which rows that operation may affect. Both therefore matter.8

RLS is not merely a checkbox.

The policy is the security model.

4. Authenticate sensitive backend routes

Frontend authentication is not backend authorization.

This distinction sounds obvious until you look at how applications are actually generated.

An AI may correctly hide an “Admin” button from ordinary users.

It may redirect unauthenticated visitors away from /dashboard.

It may show the right navigation items depending on the user.

None of that protects the backend endpoint being called.

An attacker can bypass your interface completely and send HTTP requests directly to the API.

Every sensitive backend operation therefore needs server-side enforcement.

Routes that create, modify or delete data deserve particular scrutiny, as do routes exposing private information or privileged functionality.

The core question is:

If I call this endpoint without using the application interface, does the server itself reject me?

OWASP's current secure-code-review guidance explicitly calls for server-side access control, default-deny behaviour, IDOR prevention, protected administrative functions and server-side validation of authorization rules.11

5. Authentication is not enough: verify ownership and authorization

This is probably the most important distinction for a vibe coder to understand.

Authentication answers:

Who are you?

Authorization answers:

Are you allowed to do this?

Consider:

GET /api/orders/123

The server verifies that the requester is logged in.

Good.

It then executes something equivalent to:

SELECT * FROM orders WHERE id = 123

Bad.

The user's session is valid, but nothing proves that order 123 actually belongs to them.

If changing 123 to 124 reveals another user's order, the application has an object-level authorization vulnerability commonly associated with IDOR/BOLA-style failures.

The large 2026 deployed-application study found Broken Access Control to be the largest category in its entire vulnerability dataset, accounting for 36% of all validated vulnerabilities.1

Tenzai's separate 2026 experiment reached a similar conclusion from a much smaller but controlled test.

Researchers asked Cursor, Claude Code, Codex, Replit and Devin to build equivalent applications. Across 15 applications they reported 69 exploitable vulnerabilities, with authorization and business-logic errors among the recurring problems.2

One generated application checked ownership only for users with one particular role, accidentally allowing users with other roles to access arbitrary orders.

Another performed an ownership check only if the requester was authenticated. As a result, an unauthenticated request skipped the check entirely and could reach the deletion operation.2

These are not syntax mistakes.

They are logic mistakes.

That is precisely why they are dangerous.

For every user-owned or tenant-owned resource, ask:

  • Can another logged-in user access it?
  • Can another tenant access it?
  • Can a lower-privilege role invoke an administrator operation?
  • Does the ownership check cover every code path?
  • Is authorization enforced before the sensitive operation?
  • Does the database query itself include the ownership constraint?

Changing IDs between two test accounts remains one of the simplest and most valuable manual security tests you can perform.

6. Validate input on the server — including business logic

One major weakness in many simplified security checklists is that they focus heavily on configuration while barely mentioning input.

That is a mistake.

Injection represented 17.7% of all validated vulnerabilities in the 2026 deployed-app study.1

But input security goes beyond classic SQL injection.

OWASP distinguishes between syntactic validation and semantic validation.

Syntactic validation asks:

Is this value shaped correctly?

Semantic validation asks:

Does this value actually make sense here?

OWASP recommends performing validation server-side because browser-side JavaScript can be bypassed by someone calling the backend directly.9

For example, an application may correctly ensure that a quantity is an integer.

But:

-500

is also an integer.

Tenzai's experiment demonstrated exactly this kind of failure. Four of the five coding agents tested allowed a negative order quantity, while three of the five accepted negative product prices.2

A normal user will never try to purchase -5 items.

An attacker will.

Pay particular attention to values such as:

  • price;
  • quantity;
  • account balance;
  • discount;
  • user role;
  • ownership identifiers;
  • subscription tier;
  • permissions;
  • destination URLs;
  • filenames and paths;
  • database filters;
  • HTML content;
  • redirect destinations.

Never trust a value simply because your own frontend generated it.

The attacker owns the frontend.

7. Watch server-side URL fetching for SSRF

Modern applications increasingly include features such as:

  • URL previews;
  • image importers;
  • webhook testers;
  • document importers;
  • metadata extraction;
  • remote file processing;
  • “fetch this website” AI features.

These features often cause the server to make a request to a URL supplied, directly or indirectly, by the user.

That creates the possibility of Server-Side Request Forgery (SSRF).

Instead of requesting:

https://example.com/image.png

an attacker may attempt to make your server contact internal infrastructure that cannot normally be reached from the public internet.

This class of vulnerability is particularly interesting in AI-generated applications because there is no universal safe rule saying which URL is legitimate and which is malicious. The answer depends on the application.

Tenzai deliberately included a user-controlled link-preview feature in its experiment.

All five coding agents introduced SSRF in that scenario.2

This does not mean every AI-written URL fetch is vulnerable.

It does mean that whenever attacker-influenced data reaches a server-side HTTP client, the path deserves careful analysis.

8. Apply CSRF protection where the authentication model requires it

Cross-Site Request Forgery is often oversimplified.

A security scanner should not automatically report:

“No CSRF library detected — vulnerability.”

Whether CSRF applies depends heavily on how authentication works.

It is especially important when a browser automatically sends authentication credentials — commonly cookies — with requests.

A malicious website may then attempt to cause the user's browser to perform an authenticated action against another service.

Tenzai reported that none of its 15 generated applications included proper CSRF protection. Two attempted to introduce mitigation, but the researchers concluded that both attempts were ineffective.2

The correct approach is therefore contextual.

For cookie-authenticated state-changing operations, inspect things such as:

  • CSRF tokens;
  • origin validation;
  • cookie SameSite behaviour;
  • whether GET requests perform state changes;
  • framework-level CSRF protections.

A stateless API requiring an explicitly attached bearer token has a different threat model.

Security scanning becomes considerably more useful when it understands that difference.

9. Rate-limit the endpoints attackers would abuse

Not every endpoint needs the same rate limit.

Prioritise operations where repeated requests have security, financial or resource consequences:

  • login;
  • account creation;
  • OTP verification;
  • password reset;
  • email verification;
  • invitation sending;
  • payment actions;
  • expensive AI generation;
  • resource-heavy uploads;
  • passwordless login links.

In Tenzai's 15 generated applications, nearly every login implementation lacked meaningful rate limiting or account lockout protection. The single rate-limiting implementation highlighted by the researchers relied on attacker-controllable X-Forwarded-For behaviour and could be bypassed.2

The lesson is not merely:

“Have a rate limiter.”

It is:

Rate-limit the right operation using an identity signal the attacker cannot trivially manipulate.

10. Security headers are useful — but do not confuse hardening with exploitation

Several browser security headers remain useful defence-in-depth.

Depending on the application, these can include:

  • Content-Security-Policy;
  • Strict-Transport-Security;
  • X-Content-Type-Options;
  • framing restrictions such as CSP frame-ancestors;
  • Referrer-Policy.

Tenzai found that none of its generated applications implemented the collection of security headers it examined.2

That makes security headers a worthwhile automated check.

But severity matters.

Missing CSP is not equivalent to an endpoint exposing another customer's private records.

A good security report distinguishes between:

Exploitable vulnerability
There is a credible path to violating a security boundary.
Likely security weakness
Protection appears to be missing, although exploitability cannot be completely proven from the available evidence.
Hardening recommendation
A defence-in-depth measure is absent, but no direct vulnerability has been demonstrated.

That distinction prevents security reports from becoming a wall of technically correct but badly prioritised warnings.

11. CORS should be analysed, not pattern-matched

Access-Control-Allow-Origin: * attracts a lot of security warnings.

Sometimes correctly.

Sometimes not.

A public API intentionally designed to be read by any website may legitimately allow any origin.

The more concerning patterns include sensitive APIs allowing unexpected origins, insecure origin reflection and configurations that interact badly with credentialed requests.

And one point matters above everything else:

CORS is not authentication.

It is a browser cross-origin access policy.

An attacker does not have to use a browser.

Never rely on CORS to protect information that should require authorization.

So instead of reporting:

Wildcard CORS detected → High

a useful security scanner should ask:

  • Is the resource intentionally public?
  • Does it return user-specific information?
  • Is authentication cookie-based?
  • Are credentials permitted?
  • Is the request origin reflected without validation?
  • Is server-side authorization also present?

Context determines severity.

12. Do not leak internal errors into production

Errors are valuable to developers.

They can also be valuable to attackers.

Raw database errors, stack traces, framework internals, filesystem paths and detailed exceptions may reveal information about how an application is structured.

Production clients generally should receive controlled error responses while detailed diagnostics are retained securely in server-side logging.

But “silence all errors” is not the goal either.

An application that catches every exception and discards it may hide attacks and make incidents impossible to investigate.

The better principle is:

Do not expose sensitive diagnostic information to users. Preserve useful diagnostic information securely for operators.

OWASP's 2025 Top 10 includes Mishandling of Exceptional Conditions as a dedicated category, covering classes of failure involving improper error handling, logical mistakes and systems that fail open during abnormal conditions.10

13. Check dependencies too

AI-generated applications still use ordinary software dependencies.

That means they inherit ordinary software supply-chain risk.

The OWASP Top 10:2025 places Software Supply Chain Failures at A03, expanding the older concept of vulnerable and outdated components to encompass broader failures involving dependencies, build systems and software distribution.10

Check:

  • package versions;
  • lockfiles;
  • known vulnerabilities;
  • abandoned packages;
  • transitive dependencies;
  • suspicious package names;
  • installation scripts;
  • dependency provenance where relevant.

This is not uniquely a vibe-coding problem.

But vibe coding can make the issue less visible because the user may not even know which packages the coding agent installed.

14. Treat temporary, demo and bypass logic as suspicious

This category deserves far more attention in AI-generated projects.

Search for things such as:

  • TODO;
  • FIXME;
  • temporary;
  • demo;
  • mock;
  • bypass;
  • skip auth;
  • fallback passwords;
  • test accounts;
  • hardcoded admin roles;
  • placeholder authorization;
  • debugging routes;
  • commented-out security checks.

The danger is not the word itself.

The danger is unfinished security behaviour surviving into production.

AI agents are frequently asked to “just make it work.”

If authentication is preventing the feature from functioning, one possible local solution is to weaken the authentication.

The feature starts working.

From the user's perspective, the AI succeeded.

From the attacker's perspective, it succeeded too.

What large-scale real-world investigations are seeing

Controlled benchmarks are useful, but public deployments provide another perspective.

Escape's security research team analysed more than 5,600 publicly available vibe-coded applications gathered from sources including Lovable, Base44, Create.xyz, Vibe Studio and Bolt.

The researchers reported more than 2,000 vulnerabilities, over 400 exposed secrets and 175 instances of exposed personally identifiable information, including medical information, IBANs, phone numbers and email addresses.3

Importantly, Escape also documents the limitations of its own research.

Its sample was heavily weighted toward Lovable applications. Discovery depended partly on launch directories, Shodan and community postings, meaning easily discoverable public applications may be overrepresented. The research was also conducted as a snapshot rather than continuously.3

That means the figures should not be turned into claims such as:

“X% of all vibe-coded apps leak data.”

The sample cannot support that conclusion.

What it does demonstrate is that genuine, publicly reachable AI-built applications have been found exposing secrets, APIs and sensitive information at meaningful scale.

Escape's methodology is particularly interesting because it did not blindly accept secret-looking strings. Researchers filtered placeholders and generic identifiers and, where legally permissible, safely validated credentials using non-destructive requests. Authentication weaknesses were likewise checked by replaying requests without valid credentials or by modifying authorization information.3

That is a good model for security tooling:

Detection should produce a candidate. Verification should decide whether the candidate is real.

Another investigation found thousands of exposed corporate AI-built applications

A separate 2026 investigation by security company Red Access identified more than 380,000 publicly accessible web assets associated with leading vibe-coding platforms.

Of those, roughly 5,000 appeared to be corporate applications, and reporting on the research found that more than 2,000 contained sensitive corporate, operational or personal data exposed on the public internet.4

Again, those numbers need careful wording.

It would be inaccurate to say:

“380,000 vibe-coded apps were breached.”

That is not what the research found.

The 380,000 figure refers to publicly accessible assets discovered by the researchers.

The important lesson is simpler: software can now move from idea to public deployment so quickly that internal prototypes, operational tools and data-connected applications may reach the internet before anyone has seriously considered access control.

What does the famous “45%” statistic actually mean?

One number appears constantly in discussions of AI-generated code:

45%.

It comes from Veracode's GenAI Code Security research.

Veracode tested more than 100 language models using 80 coding tasks spanning Java, JavaScript, Python and C#, focused on several security-sensitive vulnerability classes.

Across the benchmark, approximately 45% of generated solutions failed the security tests and contained a detectable vulnerability.5

Veracode continued the same testing methodology into 2026 and reported that the overall result remained around the same level across its expanded model dataset: approximately 55% of generations passed the security test, leaving roughly 45% with a known flaw under the benchmark's tested scenarios.6

That is an important result.

But it does not mean:

“45% of all AI-generated production code is vulnerable.”

The denominator is Veracode's deliberately constructed security benchmark, not every line of AI-generated code on Earth.

The responsible claim is:

In Veracode's controlled secure-coding benchmark, AI models produced code containing a detectable vulnerability in roughly 45% of tested generation tasks.

That statement is both strong and accurate.

There is no need to exaggerate it.

AI is getting better at writing code faster than it is getting better at writing secure code

Veracode's longitudinal testing found a particularly interesting divergence.

Syntax correctness improved dramatically across model generations, reaching above 95% in its 2026 testing.

Security performance did not improve at the same rate and remained around the 45–55% range across the overall benchmark dataset.6

That captures one of the defining characteristics of modern AI coding.

The model can produce code that looks increasingly professional.

It can compile.

It can use modern frameworks.

It can explain what the code does.

It can pass functional tests.

None of those facts prove that the application's security boundaries are correct.

Functional correctness and security correctness are different objectives.

Frameworks sometimes protect AI-generated code — until business logic begins

Tenzai's research produced an interesting counterpoint to the assumption that AI coding agents are bad at every kind of security.

Across its 15 test applications, researchers did not find exploitable SQL injection or XSS in the tested scenarios.

Why?

The coding agents tended to use modern frameworks correctly.

Database queries were commonly parameterised.

Frontend frameworks escaped content in safe ways.

In other words, where secure behaviour was largely built into the framework and the correct solution followed a standard pattern, coding agents often performed well.2

Their performance deteriorated when security depended on understanding context.

Questions such as:

  • Does this order belong to this user?
  • Should this role see this object?
  • Is a negative quantity legitimate?
  • Which URLs should this server be allowed to request?
  • Should this operation be rate-limited?
  • Does this cookie-authenticated request need CSRF protection?

do not have universal answers.

They require understanding what the application is supposed to protect.

That appears to be where AI systems remain particularly vulnerable.

The real problem: security requirements are invisible requirements

This is the central lesson emerging from the research.

AI agents generally implement what users ask them to implement.

Security frequently consists of everything the user forgot to ask for.

A founder says:

“Add file uploads.”

They did not mention:

  • allowed file types;
  • maximum size;
  • malware;
  • filename sanitisation;
  • path traversal;
  • storage permissions;
  • public versus private access.

A user says:

“Add a password-reset flow.”

They did not mention:

  • token entropy;
  • token expiration;
  • single use;
  • account enumeration;
  • rate limiting;
  • session invalidation.

A user says:

“Let people share projects.”

They did not mention:

  • whether sharing is read-only;
  • whether links expire;
  • whether another tenant can enumerate IDs;
  • what happens when membership is revoked.

The AI can perfectly implement the feature request while completely missing the security specification that was never written.

That is the structural weakness security tooling needs to compensate for.

Why automated scanning matters

A security checklist is useful.

But a checklist has a fundamental weakness.

You have to remember to run it.

AI-built applications can change extremely quickly. A developer may spend two weeks implementing a traditional feature. A vibe coder can ask an agent to restructure authentication, replace the database layer or add five new endpoints before lunch.

Every substantial change can introduce a new trust boundary.

A route that was secure yesterday may have a sibling added tomorrow without the same protection.

A credential may accidentally move from a server component into a client component.

A database migration may create a new table without the same authorization policy as the others.

A “temporary” debugging change may survive deployment.

Security therefore needs to become repeatable.

At minimum, a modern AI-assisted workflow should consider:

During development

  • secret detection;
  • dependency analysis;
  • static security analysis;
  • authorization consistency checks.

Before release

  • review of sensitive routes;
  • multi-user authorization testing;
  • environment/configuration review;
  • testing of externally reachable services.

After significant changes

  • scan again.

Not because every code change introduces a vulnerability.

Because security properties can disappear silently.

Static detection is only the first half of the job

There is another major lesson from the strongest research.

Automated security tools generate noise.

The 2026 deployed-app study did not simply publish everything its automated auditing systems produced. Candidate findings went through deduplication, exploitability analysis and human validation before becoming part of the final 1,471-vulnerability dataset.1

Escape similarly describes a cleanup and verification process designed to remove placeholders, generic identifiers and noisy secret detections before counting high-confidence findings.3

This suggests a better model for AI-era security tooling:

Stage 1: Detect suspicious patterns aggressively

Find potential:

  • missing authorization;
  • dangerous data flows;
  • credentials;
  • RLS mistakes;
  • injection paths;
  • SSRF;
  • unsafe file operations;
  • exposed debug behaviour;
  • insecure configuration.

Stage 2: Gather context

Determine:

  • Is the route actually public?
  • Is authentication inherited from middleware?
  • Does another layer enforce authorization?
  • Is the credential genuinely privileged?
  • Is the data attacker-controlled?
  • Does the dangerous sink actually execute?
  • Is the endpoint intentionally public?

Stage 3: Verify

Decide whether the evidence demonstrates:

  • an exploitable vulnerability;
  • a likely security defect;
  • a hardening recommendation;
  • or a false positive.

That distinction matters enormously to non-technical builders.

If a security scanner produces 100 warnings and half of them are meaningless, the user learns to ignore the scanner.

If it produces five findings and clearly explains why each one represents a real trust-boundary failure, the report becomes actionable.

A better priority order for vibe-coded applications

Based on the research available today, a practical security review should prioritise roughly like this:

Highest priority

Authorization and ownership

  • IDOR/BOLA;
  • tenant isolation;
  • missing backend authorization;
  • administrator privilege bypass;
  • inconsistent protection between routes.

Privileged credentials

  • service-role keys;
  • backend API secrets;
  • database credentials;
  • signing secrets;
  • administrative tokens exposed to public environments.

Database authorization

  • missing RLS;
  • overly broad RLS policies;
  • dangerous database grants;
  • publicly accessible storage.

Untrusted data reaching dangerous operations

  • injection;
  • command execution;
  • unsafe HTML rendering;
  • filesystem paths;
  • unsafe redirects;
  • SSRF.

Next priority

Authentication and session security

  • unprotected routes;
  • broken token validation;
  • password-reset logic;
  • insecure cookies;
  • CSRF where applicable.

Business-logic validation

  • user-controlled prices;
  • negative quantities;
  • user-supplied roles;
  • workflow bypasses;
  • client-only security checks.

Abuse protection

  • login throttling;
  • password-reset throttling;
  • OTP abuse;
  • expensive API abuse.

Supporting hardening

Dependencies and supply chain

Security headers

CORS

Production error handling

Debug and temporary logic

Unsafe upload handling

All matter.

But they should not be presented as though they carry identical security significance.

The checklist is not a guarantee

Passing these checks does not prove that an application is secure.

Security is contextual.

A healthcare application and a public landing page have very different threat models.

An application that accepts payments has different concerns from an anonymous image generator.

A multi-tenant SaaS application has authorization problems that a single-user local tool may never encounter.

The goal of a checklist is therefore not to certify an application.

It is to catch the failures that are both common and dangerous before an attacker finds them first.

The hard part was never fixing them

Most of the vulnerabilities discussed here are not exotic.

Add the missing ownership condition.

Move the privileged credential to the server and rotate it.

Enable RLS and write the correct policy.

Validate the request server-side.

Protect the sensitive endpoint.

Restrict the URL fetcher.

Add throttling.

Disable debugging.

Remove the temporary authentication bypass.

Individually, many of these fixes can be small.

The difficult part is discovering that the protection is missing in the first place.

That problem becomes more important as AI coding gets faster.

A coding agent can create a new feature in minutes. It can also reproduce the same security omission across several routes in minutes.

The evidence available today does not show that AI-generated applications are doomed to be insecure.

It shows something more useful:

AI coding systems are increasingly capable of producing functional software, but they cannot yet be assumed to infer every security requirement that the builder forgot to specify.

The safest workflow therefore is not to stop vibe coding.

It is to separate two questions:

Does the application work?

and

Does the application enforce the security boundaries it is supposed to enforce?

Build quickly.

Then verify deliberately.

And every time the application changes in a meaningful way, ask those questions again.

Sources reviewed

  1. 1
    Deng, Fan & Meng — Understanding the (In)Security of Vibe-Coded Applications, 2026.
  2. 2
    Tenzai — coding-agent security experiment across five agents and 15 applications, 2026.
  3. 3
    Escape — analysis of 5,600+ publicly available vibe-coded applications.
  4. 4
    Red Access — publicly accessible assets on vibe-coding platforms, 2026, and the reporting on it.
  5. 5
    Veracode — GenAI Code Security Report, 2025 benchmark.
  6. 6
    Veracode — GenAI code security testing continued into 2026.
  7. 7
    Supabase — API keys documentation.
  8. 8
    Supabase — Row Level Security documentation.
  9. 9
    OWASP — input validation guidance.
  10. 10
    OWASP — Top 10:2025.
  11. 11
    OWASP — secure code review guidance.

Check your code for some of these

Epherem’s free scan reads your code for some of these problems, such as who can see and change data, keys and secrets, and input handling, and looks up your packages in the public OSV advisory database. Its code findings are potential issues, not verified: likely issues, where the scanner saw the risky code itself, and findings that need checking, where it looked for a protection and didn’t see it, or the match depends on context it can’t see. It can’t test your live site, and the report names what it couldn’t check.

Scan your app free