Journal / Security

Security is not a feature. The startup attack surface, mapped.

Most startup security failures are not sophisticated attacks. They are known patterns hit by automated tools against teams that assumed security was someone else's problem.

RL
RBB LAB
Studio
Published 14 May 2026 8 min read
0day RBB/LAB SECURITY RBB LAB · JOURNAL 8 MIN READ

Every founder we work with eventually says the same sentence, usually six weeks before they need to say something different: "we will harden it before launch." Security gets logged as a milestone, slotted between the last design review and the press embargo. It is treated like a feature you can ship in a sprint.

It is not a feature. It is a property of how you build, how you deploy, and how you respond when something goes wrong. You cannot bolt it on, because the gaps are not in any single component; they are in the seams between them, in the assumptions nobody wrote down, and in the boring operational habits that nobody puts on a roadmap.

The pattern that keeps repeating across the teams we work with is not exotic. It is the same five tiers of attack surface, hit by the same automated tools, against teams who thought their cloud provider, their auditor, or their framework was handling it. This article is the map we use when we walk in on day one.

The myth of the sophisticated attacker

The narrative in founder Slack rooms is that the dangerous attacker is a nation state with a zero day and infinite patience. The actual attacker, in our experience, is a Python script run by someone who has never heard of your company. It iterates through leaked credentials, scans GitHub for committed secrets, and pokes at every RPC endpoint that responds. It does this at machine speed against the entire IPv4 space, and yours is one row in its log.

This changes the threat model from "what would a determined adversary do" to "what would a bored adversary find in the first ten minutes." The answer, for most pre-launch teams, is a depressing list. A staging environment with default credentials. An admin panel on the public internet. A Solidity function with no access control. A `.env` file in the repo history.

Sophisticated attackers exist. They are not your near-term problem. Automation is, and automation does not need to be clever to be effective. It needs the door to be open.

Sophisticated attackers exist. They are not your near-term problem. Your near-term problem is automation, and automation does not need to be clever to be effective.

The five tiers

We organise the attack surface into five tiers. The ordering is not a priority list; every tier is independently exploitable and every tier has shipped breach headlines in the last twenty-four months. The ordering reflects how the layers sit, from operational outside to cryptographic inside.

Tier 5: Ops & incident response (outermost)
Tier 4: Supply chain
Tier 3: Smart contracts & protocol
Tier 2: Key management
Tier 1: Auth & sessions (innermost / most targeted)
Fig 1: Attack surface tiers from outermost to innermost. Every tier is independently exploitable.

Before we walk through each tier, here is the rough shape of the trade-offs. Likelihood, impact, and fix effort are the columns founders ask about first.

Illustrative likelihood/impact/effort ratings. Your situation will differ.

Tier Example attack Likelihood Impact Fix effort
Auth & sessions Credential stuffing, session fixation High High Low
Key management Leaked private key, unrotated secret Medium Critical Medium
Smart contracts Reentrancy, integer overflow, access control Medium Critical High
Supply chain Compromised npm package, typosquatting Low High Medium
Ops & incidents No alerting, no runbook, delayed response High High Low

The two tiers with high likelihood and low fix effort, auth and ops, are where every team should spend the first week. They are also the two tiers most founders skip because they feel less interesting than the cryptographic ones. That is the mistake we see most often.

Tier 1: Auth and session management

This tier gets hit first, every time. Credential stuffing is the cheapest attack on the internet: take a leaked credential dump from any breach in the last decade, replay it against your login endpoint, and see who reused their password. If you have public signups and no rate limiting, you will get tested within hours of going live. We have watched it happen on a staging URL that was never publicly announced; the bots find you through certificate transparency logs.

The fixes are unglamorous. Enforce MFA on every administrative account, with no exceptions for the founder who finds it annoying. Rate limit your auth endpoints. Lock accounts after a small number of failed attempts. Use a session store that lets you revoke sessions server side, not a stateless JWT that lives for a week. Rotate session identifiers on privilege change. Set cookies with `Secure`, `HttpOnly`, and `SameSite=Lax` or stricter. Most of this is configuration, not code.

The expensive part is the one nobody talks about: making the support flow that handles account recovery as hardened as the login flow. The attacker who cannot get in through the front door will try your customer support team, social engineering their way to a password reset. We treat the support runbook as part of the auth surface.

Tier 2: Key management

If your product holds custody of anything, keys are where breaches become headlines. The mistakes repeat. Private keys generated on a laptop, then pasted into a config file. A signing key shared in a chat thread "just for the demo." A hot wallet whose private key ended up in a build artifact because the deploy script read it from the environment and the CI logged the environment on failure.

Our rule is simple: keys that sign anything financial should never touch application memory in any environment a human can read. That means HSMs for institutional setups, secure enclaves for everything else, and a hard line that production signing keys are not exportable. The development experience suffers; we accept that. The alternative is a postmortem that starts with "we had the key in a `.env` file."

Non-signing secrets follow the same shape with less drama. Every secret in a manager, rotated on a schedule, audited on access. No long-lived API tokens. No service accounts shared across environments. The default failure mode of small teams is to share one set of credentials across staging and production "until we have time to fix it." We have never seen a team that found the time before the incident.

Tier 3: Smart contract risk

If you ship onchain, this is where the largest single losses come from. The bug classes are by now folklore. Reentrancy, integer overflows on math that should have used a safe library, access control modifiers missing on functions that mint or withdraw, price oracle manipulation when a contract trusts a spot price from a thin pool. None of these are new. All of them keep shipping.

The non-negotiables are independent third-party audits before mainnet, formal verification on the truly critical paths, and a deploy process that does not let a single engineer push a contract to production. We use timelocks on admin functions and multisigs on anything that can move funds or upgrade logic. We design the upgrade path before we deploy the first version, not after we discover the bug.

One pattern we now insist on: every onchain protocol gets a parallel offchain accounting service that independently tracks balances and flags any divergence. If the contract says the pool holds 1,000 units and our books say 998, we want to know within seconds. This is also why we are careful about which AI tools we let near contract code. We discussed our position in our piece on vibe coding: tools like Fable 5 and Mythos 5 are restricted because the same capability that writes contracts well can also automate vulnerability discovery against deployed ones.

Tier 4: Supply chain

The npm ecosystem publishes thousands of packages a day. Your fintech app probably depends, transitively, on a few thousand of them. Each is a place where a maintainer can be compromised, a typosquat can land, or a malicious update can ship as a patch release that your CI pulls in automatically.

We pin dependencies by hash, not just version. We use lockfiles and check them into source control. We treat `npm install` in CI as a code review event. We isolate build environments so a compromised post-install script cannot exfiltrate secrets production never needed to see. For dependencies that touch signing, cryptographic operations, or financial transaction parameters, the bar is higher. We review every release of any such package, sit on updates for a week, and run them against staging before production.

Tier 5: Ops and incident response

The outermost tier is the one founders mentally classify as "not security." It is. The most expensive part of any breach we have seen up close was not the initial compromise; it was the four hours between when the attacker got in and when anyone on the team noticed. Detection latency is impact multiplier.

Centralise your logs. Alert on auth anomalies, key usage, unexpected outbound network calls, and any privileged operation outside business hours. Write a runbook for what to do when an alert fires, and make sure that runbook is accessible without production access, because the first thing you may lose in a compromise is production access. Test the runbook with a tabletop exercise once a quarter. Most teams never test theirs; the first run is during the actual incident, and it shows.

Have a way to revoke credentials, rotate keys, and isolate compromised services in minutes. Have a person on call who knows where the kill switches are. Have a communications template ready for the moment you need to notify customers or regulators. The hard part is not the technical response. It is the decisions you make under pressure, in front of an audience. Pre-deciding removes most of the cost.

Where to start this week

If you read this and felt the familiar pull of "we should really do all of this, after the next release," here is the short list we hand teams who want measurable progress in one week. None of these items requires an architectural change. All of them remove failure modes we still see in real audits.

  1. MFA enforced on all admin accounts and external-facing services.
  2. All secrets in a secrets manager, not in code or .env files committed to git.
  3. Dependency audit passing (npm audit / cargo audit / go vet) with zero high-severity issues.
  4. Private keys generated in HSM or secure enclave; never touch application memory.
  5. Smart contracts audited by an independent third party before mainnet.
  6. All third-party packages pinned by hash, not just version.
  7. Logging captures auth events, key usage, and anomalous API calls.
  8. Incident runbook written, tested, and accessible without prod access.
  9. Rate limiting on all auth endpoints; account lockout after N failures.
  10. Penetration test completed in the last 12 months (or scheduled).

Read the list. Be honest about which items are green, which are yellow, and which are red. Send the red ones to whoever owns them and put a date on each. That is the entire exercise.

Security is not a feature you ship. It is a property of how your team works, expressed in a hundred small decisions you make before you ever face an incident. The teams that survive their first serious test are not the ones who hired the most senior consultant. They are the ones who treated boring operational hygiene as the work, not the prelude to it.

If you want a second pair of eyes on your current setup, we are reachable.

RL
RBB LAB
Studio · San Marino
A small team of senior engineers building production software for businesses and founders. We ship, hand off, and disappear cleanly.
Stay in the loop

One email when we publish. Nothing else.

About once a month. Sometimes less. No funnels, no drip campaigns.

Or grab the RSS · Follow on LinkedIn / X