Lovable didn’t get hacked. It exposed data.
A flaw in the API allowed any authenticated user to access projects they didn’t own. Source code, database credentials, chat history: everything was available through valid requests. The system checked authentication, saw nothing unusual, and returned a clean response. 200 OK.
That’s how the incident is being explained. A missed authorisation check. A familiar BOLA flaw. Something that should have been caught and fixed.
And all of that is true. But it’s not the interesting part.
Because if you stop there, you reduce this to a bug. And this wasn’t just a bug.
The part that should make everyone uncomfortable
Look at what was actually exposed.
Not just user data, but artifacts that only exist because the system created them: database credentials embedded in code, service role keys copied into workflows, internal logic assembled from natural language interactions, and entire application structures generated on the fly.
This wasn’t just stored content. It was constructed content. It existed because the system decided it should exist. And then it exposed it.
Even if the API had been perfectly implemented, the system was already accumulating things that were never meant to become a persistent, accessible state. The leak only made visible what was already structurally fragile.
This didn’t start at the API layer
The natural instinct is to fix the endpoint. Add ownership checks. Tighten access control. Close the vulnerability. Make no mistake, that’s necessary. But it doesn’t solve the underlying problem.
Because the failure didn’t begin when someone accessed the data. It began when the system decided what should be created, stored, and treated as part of the application itself. By the time the API served that data, the decision had already been made.
The system is doing more than serving data
Lovable is not just an API platform. It is a system that takes natural language input and turns it into working software. A user request becomes code, configuration, credentials, and integrations. These outputs are not static, they are generated, refined, and assembled dynamically.
That distinction matters. This is not a system executing predefined behavior. This is a system constructing behavior.
And construction is where things go wrong
Consider a simple flow. A user is building an application and pastes credentials into a chat to debug an issue. The system incorporates them into generated code. The project evolves. Artifacts accumulate. Nothing in this process looks incorrect in isolation. But something subtle happens.
The system begins to accumulate more capability than the original task required. What started as a narrowly scoped request becomes a broader system with access to sensitive data, external integrations, and internal logic that was never explicitly authorized.
Nothing breaks. But the system becomes more powerful than intended.
This pattern shows up everywhere
Lovable is not an outlier. You see the same structure in other failures: agents leaking secrets through prompt injection, systems exporting sensitive data to external APIs because it improves task completion, AI-generated applications exposing internal endpoints that were never meant to be public.
In each case, everything looks valid. Authentication passes. Permissions are respected. Execution is correct. And yet the outcome is wrong. This is not a failure of execution. It is a failure of construction.
Why traditional security keeps missing it
Traditional security systems are built to answer a specific set of questions: who is acting, what they can access, and where the action is happening.
Those questions work when behavior is predefined. They don’t work when behavior is being created in real time. Because they never ask the question that matters here:
Should this behavior exist at all?
The system is not a set of actions
It is a chain. A request moves through a sequence of transformations: from purpose to intent, from intent to plan, from plan to artifacts, and finally to execution. At each step, ambiguity is reduced. The system becomes more certain. Decisions are made. Assumptions are introduced. Capabilities expand. The system becomes more concrete. And often, more powerful. This is where things break.
The dangerous transition
There is a moment in every system like this where something shifts. The system stops exploring possibilities and starts committing to a direction. At that moment, data becomes code, code becomes capability, and capability becomes execution. If the system is allowed to expand what it can do at that moment, everything that follows will be valid. And still wrong.
What controlling the right layer actually means
Controlling the right layer does not mean adding more checks at the API. It does not mean adding more policies at execution. It means introducing a constraint earlier, at the point where the system decides what to build. A system should be free to explore possible plans. But not all plans should be allowed to become real.
Before something becomes part of the system, it should be evaluated for whether it expands capability beyond what was originally intended, whether it introduces new access paths, or whether it weakens implicit constraints. If it does, it should never become part of the system state.
And only then does execution matter
Once the system has constructed something that is properly bounded, execution becomes enforceable. Actions can be validated. Behavior can be verified. Access can be controlled.
But that only works because the thing being executed was already constrained. Without that boundary, execution controls are too late. They validate the result. Not the decision that created it.
Take away
We have been securing systems at the level of action. But these systems don’t just act. They decide what to become. If you don’t control what the system is allowed to become, you won’t be able to control what it eventually does.



