Build It vs Break It: Why Vibe Coders Keep Shipping Apps That Are Easy to Hack
There is a pattern that keeps playing out. A developer or vibe coder builds an app in a short amount of time, deploys it publicly, gets traction on social media, and then a while later someone replies - the database got leaked.
Not because the developer was incompetent. Not because the technology stack was bad. But because one thing kept getting skipped when the focus was entirely on speed: security.
This article is about the Build It vs Break It mindset. Why does it matter? Where do vibe coders tend to drop the ball on security while staying focused only on the end product? And how do you shift your thinking to be more security-aware without sacrificing development speed? I’ll try to cover it here without going too deep.
Two Mindsets That Keep Clashing
In software development, two extremes tend to collide:
The first is the “just ship it” mentality. The priority is speed: feature done, demo works, deployed. This is not inherently wrong, especially during early-stage idea validation or MVP development. The problem shows up when this mentality carries all the way into production - even after real users are on the platform. And it does not help that many people at the management level keep pushing developers to move faster, which makes this approach feel like the only viable one.
The second is the “it has to be perfect first” mentality. This type of developer gets stuck in every corner of the codebase. That creates its own set of problems - the product never ships, and the competition moves faster.
But there is another dimension that both extremes tend to miss: is this application actually secure?
Not “does it have a login page?” - but secure in the real sense. Secure against input manipulation. Secure against unauthorized access. Secure against unintentional data exposure. Everyone wants their app to be secure, but during the development process it often gets left behind because it is seen as something that slows things down.
What Is Build It vs Break It?
The concept is straightforward. You build something, then you analyze it or actively try to break it yourself before someone else does.
Build It is the standard development process within the Software Development Lifecycle (SDLC), where a system is designed, implemented, and integrated based on functional requirements - covering feature design, writing code, and deployment so the application can be used as intended.
Break It represents threat modeling within a Secure Software Development Lifecycle (Secure SDLC), where the system is analyzed from an attacker’s perspective to identify potential misuse scenarios, attack surfaces, weak input validation, and gaps in authentication and authorization mechanisms.
This is not about being paranoid. It is about being aware that every system you build will eventually be used by people - and some of them will try things you never anticipated.
If you built it, you should ideally be the first one to find the holes - not someone else.
The Vibe Coding Phenomenon and What Hides Behind It
The term “vibe coding” became popular to describe a development style that relies heavily on AI tools like Cursor, Copilot, Claude, or ChatGPT to write almost all of the code. The developer describes what they want, the AI writes it, and the output gets pasted in directly.
This is not fundamentally a bad thing. AI tools genuinely do speed up development. The problem is not the tools themselves - the problem is how developers use them without understanding what gets generated.
When you generate code without understanding the flow, you will not know:
- Whether that code validates input correctly
- Whether there are wrong assumptions about who can access a certain endpoint
- Whether sensitive data is leaking through API responses
- Whether a library being used has a known vulnerability
The result is an application that looks polished, demos smoothly, but underneath is full of gaps the developer never noticed.
From Viral to Breached: A Repeating Pattern
If you spend time on X (Twitter), you have probably seen this pattern:
Someone posts “I built this app in 2 hours using AI”, gets thousands of likes and retweets. People start trying it out. Traffic spikes. Then not long after, someone finds a hole. The database gets dumped. Shortly after, the app goes offline.
This is not a one-off event - it has happened repeatedly, and the frequency keeps climbing as vibe coding grows more popular.
Why does this happen? Usually a combination of several things:
- First, apps get deployed directly to production with no security review at all. Nobody sat down and asked “what happens if someone tries to inject SQL here?”
- Second, endpoints that should be protected are not. There might be a login check on the frontend, but nothing on the server side.
- Third, API keys and credentials sometimes get pushed to public repositories because the developer did not understand how to manage secrets properly.
- Fourth, there is no rate limiting, so anyone can fire thousands of requests per minute for brute force or data scraping.
- Fifth, there are plenty more where those came from.
The principle is simple: the moment you expose something to the internet, bots are scanning and probing it within minutes. This is not an assumption - it is a fact. If you have a public VPS, check your SSH login attempt logs right now.
Seven Common Problems That Keep Showing Up
Security by Accident
Many applications that “have never been attacked” are not secure - they just have not been found yet, or nobody has bothered targeting them. That is very different from being “secure by design”.
Security by accident means you got lucky. And luck is not a strategy you can rely on, especially once your application has real users and real production data.
Over-Reliance on Framework Defaults
Modern frameworks like Laravel, Django, Rails, or Next.js come with a lot of built-in security features. But this often gets misread as “the framework handles everything, I just have to use it.”
The reality is that a framework only helps you avoid common mistakes - it cannot replace your own understanding of what is actually happening. When you do not understand how session management, token validation, or CSRF protection works, you can easily misconfigure something that should be safe and turn it into a vulnerability.
It all comes back to the person behind the tool. Using a framework does not stop you from breaking the rules the framework was built around.
Copy-Paste Driven Development
Stack Overflow, Reddit, and AI tools are genuinely useful resources. But there is a difference between understanding code you find and just copying it.
Code from the internet - including AI-generated code - is often written for a different context. Examples written to demonstrate a concept usually do not include security considerations. If you paste it in directly without modification or understanding, you can unknowingly introduce a vulnerability.
No Threat Modeling
Threat modeling is a simple process where you sit down and ask: who might attack this system, what do they want, where can they get in, and does each part of the application account for that?
Very few developers do this, and vibe coders rarely do. But it does not have to be formal or require special tools. Basic questions like: is there data here worth stealing? Who should not be able to access this feature? What happens if someone sends unexpected input?
Without a threat model, you are building a system with a large blind spot.
Insecure by Design
A poorly designed API is one of the biggest sources of vulnerabilities in modern applications. A few common patterns:
Endpoints returning more data than necessary - for example, /api/user/123 returning the entire user object, including the password hash and internal fields that should never leave the server.
Predictable IDs. If you can access /api/order/1001, try /api/order/1000 - does someone else’s order show up? This is called IDOR (Insecure Direct Object Reference) and it is one of the most common vulnerabilities in the OWASP Top 10.
No proper authorization check. There might be authentication (proving who you are), but no authorization (proving you are allowed to access this resource).
Debug Mode in Production
This happens more often than you would think. A developer forgets to turn off debug mode before deploying to production, and the result is highly detailed stack traces appearing on every error.
To an attacker, this is a roadmap. A stack trace can reveal file names, directory structure, library names and versions, and sometimes pieces of the code being executed. All of that can be used to craft a more targeted attack.
“Works on My Machine” Mentality
Testing only in a local development environment is not enough. Production has different characteristics - different configuration, different variables, and most importantly, unpredictable users.
Without proper testing - and especially without any security testing - you have no accurate picture of what your application looks like in the real world.
The Break It Mindset: Questions to Ask Every Time
Every time you finish building a feature, get into the habit of asking yourself:
- What happens if someone puts weird characters, HTML script tags, or a SQL query into this input field? Does the application handle it correctly or crash?
- Can this endpoint be accessed by a user who is not logged in? If not, is the check happening on the server or just in the frontend?
- If I have a regular user account, can I access data or functionality that should only be for admins?
- Is my API response returning more information than the client actually needs?
- What happens if someone sends thousands of requests to this endpoint in one minute?
These questions do not require expert knowledge to ask. They just require habit and discipline.
Fundamentals That Keep Getting Skipped
Input Validation
Every piece of data coming from a user should be treated as untrusted until proven otherwise. This is the most basic principle in web security.
A vulnerable example:
// INSECURE SQL QUERY
const query = "SELECT * FROM users WHERE username = '" + req.body.username + "'"
If someone enters ' OR '1'='1 as the username, that query returns every user in the database. This is SQL Injection 101 - one of the oldest vulnerabilities on the web, and it still shows up everywhere.
Use parameterized queries or prepared statements instead:
// Secure SQL Query
const query = "SELECT * FROM users WHERE username = ?"
db.execute(query, [req.body.username])
Beyond SQL Injection, input validation also matters for preventing XSS (Cross-Site Scripting), where an attacker injects HTML or script tags into a page that other users will see.
Authentication and Authorization
Authentication means confirming who is accessing the system. Authorization means confirming they are only allowed to access what they are permitted to access.
Both need to happen server-side, not just on the client. Hiding a button in the frontend is not authorization - it is just a view. Anyone can send requests directly without touching the UI, and there are many ways to get around frontend-only restrictions.
Passwords and Credentials
Passwords must never be stored as plaintext, and hashing them with MD5 or SHA1 is not enough. Use an algorithm built specifically for password hashing like bcrypt or Argon2, which are designed to be computationally expensive and resistant to brute force.
Never hardcode API keys, database credentials, or any secrets directly in the code. Use environment variables and make sure the .env file never ends up in the repository, and especially never accessible from the public internet.
Rate Limiting
Without rate limiting, any endpoint in your application can be hammered with thousands of requests in a short period. Login endpoints can be brute-forced. API endpoints can be scraped clean. Even endpoints that seem “unimportant” can be used in a distributed denial of service attack.
Rate limiting does not have to be complex - most frameworks and platforms already provide easy-to-use solutions.
CSRF
Cross-Site Request Forgery is an attack where an attacker tricks a victim into unknowingly sending a request to your application using the victim’s active session. Without CSRF protection, an attacker can set up a form on their own site that, when the victim clicks it, sends a request to your application on the victim’s behalf.
Bringing Build and Break Together in Your Workflow
This mindset is not about slowing down development. It is about making sure what you build does not need to be rebuilt from scratch after an incident.
A few practical things you can start doing right now:
- Before deploying, take 15-30 minutes to try “attacking” the feature you just built. Try strange edge cases. Try hitting endpoints directly without going through the UI.
- Use a tool like OWASP ZAP or Burp Suite (the community edition is free) for basic security scanning. You do not need to be an expert to run them.
- Set up proper logging. You cannot defend what you do not monitor. Know when there is unusual activity in your application.
- Follow vulnerability disclosures for the frameworks and libraries you use. When a security update comes out, do not put it off.
On the Trade-off Between Speed and Security
There is a common assumption that security slows you down. This is not entirely wrong - there is a real trade-off here. But that trade-off tends to be overstated.
Security best practices like parameterized queries, input validation, and proper authentication do not add significant time once they become habit. What costs a lot of time is cleaning up after an incident - investigation, communicating with users, fixing the system, and rebuilding trust.
Speed that sacrifices security is technical debt, and this particular debt comes with a very high interest rate.
Closing
Many applications do not fail because of complex technical reasons. They fail because of the wrong mindset from the very beginning.
Vibe coding is not the problem. Using AI to speed up development is not the problem. The problem is when speed becomes the only measure of success and security gets treated as something that can be sorted out later.
On the internet, “we’ll fix it after something goes wrong” is not a viable plan - because when something does go wrong, it is often already too late. The data is already out. The user trust is already gone.
Make “how could someone misuse this?” a routine question, not an afterthought. Build fast, but build with intention and with your eyes open.
Because the moment your application goes online, someone is already trying to break in. Better if you are the one who finds the holes first.