I want to tell you about a startup that no longer exists.

They had genuine product-market fit, a motivated team, and a Series A term sheet on the table. What they didn't have — and didn't know they were missing — was a single authorization check in their API middleware.

That gap cost them everything.

I'm not sharing this to be dramatic. I share it because in three years of security research and auditing, I've seen variations of this story play out multiple times. The details change. The pattern doesn't. And the pattern is almost always invisible until it's too late.

Let me walk you through what actually happened — and more importantly, why it keeps happening.

The Company: A Quick Sketch

I'll call them Helix (not their real name). They built a B2B SaaS platform for operations teams — the kind of product that handles employee data, internal workflows, and sensitive process documentation. About 300 customers. Real revenue. A technical co-founder who knew what they were doing.

Their authentication was solid. JWT tokens, properly signed, appropriate expiry windows. If you'd asked their team about security, they'd have given you a thoughtful answer about their auth implementation.

The problem wasn't authentication. It was authorization.

The Difference That Cost $2.3 Million

Authentication answers: who are you?

Authorization answers: what are you allowed to do?

These are different questions. And in Helix's middleware, only the first question was being asked.

Here's a simplified version of what their API routing looked like:

// Middleware: verify token exists and is valid
const verifyToken = (req, res, next) => {
const token = req.headers.authorization;
if (!token || !jwt.verify(token, SECRET)) {
return res.status(401).send('Unauthorized');
}
next(); // ← proceeds to route handler
};

Notice what's missing? The middleware checks that you have a valid token — but it doesn't check whether the resource you're requesting belongs to your account.

An attacker with a legitimate free account could change a single number in a URL and read any other customer's data. Change the number again — another customer's data. There was no check between 'valid user' and 'authorized to access this specific resource.'

How the Breach Actually Unfolded

Someone discovered the vulnerability during what appeared to be a routine account signup. Within 48 hours, data from dozens of customer accounts had been exported. Helix's monitoring caught unusual API activity on day three.

By then, the data was gone.

The breach notification process started. Customers were informed. Legal counsel was engaged. And then the Series A process, which had been progressing smoothly, hit a wall.

Investors paused. Their legal team initiated a security review. The review surfaced the breach. The breach entered the due diligence record.

What followed was eight months of uncertainty, legal process, and customer churn. The round never closed at the original terms. The company ran out of runway nine months after the breach was detected.

The Part That Stays With Me

After the dust settled, I had a chance to review the codebase. The fix — adding a single ownership check to the middleware — would have taken an experienced developer about 90 minutes to implement and test.

Ninety minutes. Against eight months and a company.

The authorization check wasn't skipped because the team didn't care. It was skipped because they were moving fast, the authentication was working, and nobody stepped back to ask whether authentication and authorization were two separate concerns that needed two separate solutions.

That's the real lesson. Not 'write secure code or else.' It's that certain categories of vulnerability emerge naturally from the conditions of early-stage software development — small teams, fast timelines, iterative architecture — and they require deliberate attention to surface before someone else finds them.

What 'Authorization' Actually Means for a SaaS Product

If you're building a multi-user SaaS application, here's a simplified mental model worth keeping:

  • Authentication: Does this person have a valid identity in our system?
  • Role-based authorization: Is this person allowed to perform this category of action (e.g., admin vs. viewer)?
  • Resource-level authorization: Is this specific person allowed to access this specific record?

Most early SaaS products implement the first two reasonably well. The third one — resource-level authorization — is where I consistently find gaps. It's also the one that produces the highest-severity findings in audits, because it's the check that stands between an authenticated user and every other user's data.

A Note on Why I Write About This

I spent several years as a bug bounty hunter before transitioning to structured security audits. The shift changed my perspective significantly. In bug bounty work, you're looking for the most impactful finding in the shortest time. In an audit, you're looking for completeness — every gap that matters, in context, with a clear path to resolution.

What I carry from both is a deep familiarity with the patterns. Authorization gaps. Missing rate limits. Business logic vulnerabilities that no automated scanner touches. I've seen them enough times across enough products that they've stopped feeling like surprises.

Writing about them is my version of doing something useful with that pattern recognition before another Helix happens.

If you're a SaaS founder who has been putting off a security review, I offer a free 30-minute architecture call. No pitch — just an honest assessment of whether your current setup warrants a deeper look