All news
    SecurityEngineering

    Threat Model Tuesday: what happens if Pwdly gets breached tomorrow?

    A walk through the worst day of our company life — a full database dump in the wild — and exactly what an attacker would, and wouldn't, walk away with.

    The Pwdly Team
    Engineering & Security
    28 April 2026
    5 min read
    Threat Model Tuesday: what happens if Pwdly gets breached tomorrow?

    Most security writing dances around the awkward question: what if you, the company asking us to trust you, get owned? So let's just go there. It's Tuesday. Imagine our worst week. Some configuration drifts, a backup ends up where it shouldn't, an attacker gets a copy of the entire Pwdly production database and dumps it on a forum somewhere. What happens to you?

    This is the scenario we designed Pwdly around from day one. Not because we expect it — we work hard to make sure it doesn't happen — but because the only honest answer to "is my data safe?" is the one you can give after assuming the server has already lost. So this is Threat Model Tuesday. We're going to walk through that bad day in detail.

    What an attacker actually gets

    If someone walks off with the entire Pwdly database, here's what's in their hands. Rows of credentials where every meaningful field — the site name, the username, the email, the password, the URL, the notes — is a base64 blob produced by XChaCha20-Poly1305. Project names: encrypted. Folder names: encrypted. Custom fields: encrypted. The metadata that has to stay legible for the system to function — user UUIDs, project UUIDs, the mapping of which user belongs to which project, timestamps — that's it.

    They'd also get the wrapped key material: per-user keys that are themselves encrypted with a key derived from your 3-word recovery phrase, and per-project keys wrapped for each member. Wrapped, in this context, means "useless on its own." Without the input that unlocks them, they're just more high-entropy noise.

    Notice what's not in the dump. Your master password isn't there — we never receive it. Your 3-word recovery phrase isn't there — that's generated locally and never transmitted. The keys that actually decrypt your vault aren't there in any usable form. The plaintext of a single password isn't there. Not one.

    Why brute-forcing the dump goes nowhere

    The obvious next move for a determined attacker is to take the wrapped keys and try to guess what unlocks them. This is where Argon2id earns its keep. The key that wraps your data is derived from your recovery phrase using Argon2id with 64MB of RAM and 2 iterations per attempt, plus a per-user salt. That's not a number we picked because it sounded big. It's tuned so a single guess takes real time and real memory, on real hardware, even on a GPU farm.

    Combine that cost-per-guess with the entropy of a 3-word phrase from our wordlist and you're looking at a search space measured in centuries of compute, per user. Not per database — per user. An attacker doesn't get to crack one and unlock everyone; the salt makes every account its own independent problem. There is no shortcut, no "master key," no admin override sitting somewhere on our infrastructure that flips the whole thing open.

    What about the metadata?

    Let's be honest about the parts that aren't encrypted, because pretending otherwise would be the kind of marketing we built Pwdly to get away from. The server has to know which user is which to log them in, so user UUIDs and email addresses exist in plaintext on the server side. It has to know which users are in which projects to route invites and permissions, so the membership graph — UUID to UUID — is visible too. Timestamps are stored as timestamps.

    What an attacker can do with that is limited and worth being precise about. They could see that a particular email address has a Pwdly account. They could see that account belongs to some number of projects, identified by opaque UUIDs. They cannot see the names of those projects, the credentials inside them, or anything about what those credentials protect. They cannot see who the other members are by name — only by UUID, which maps back to email addresses but not to anything else.

    It's a real disclosure. We don't want to handwave it. But it's the disclosure of the existence of an account, not the contents of a vault, and we've worked to keep that surface as small as the product will allow.

    Shared projects: still safe

    Sharing is the place a lot of zero-knowledge designs quietly fall apart, so it deserves its own paragraph in the bad-day scenario. When you invite a teammate to a project, the project key is wrapped using a one-time invite key derived — again with Argon2id — from a 6-digit code, the invitee's email, and a random salt. The 6-digit code is delivered out-of-band: you read it to them, send it through a different channel, however you want. The server only ever sees the wrapped result.

    In a database breach, the attacker gets the wrapped invite payload. They don't get the 6-digit code, because the code never lived on our servers. Without both, the wrapped project key is just more noise. Once the invitee accepts, the project key is re-wrapped with their own master key and the invite payload becomes inert. Even an outstanding, unaccepted invite doesn't hand an attacker the keys to the project.

    What we'd actually do that morning

    All of the above is what makes a breach survivable. It is not what makes it a non-event. If we ever discovered an unauthorized copy of our database in the wild, here's roughly what the day would look like. We'd contain the source: rotate infrastructure credentials, take affected systems offline, get forensics on the host. We'd notify users — clearly, in plain language, with what was disclosed and what wasn't, on a timeline that respects both the law and your patience.

    We'd publish a post-mortem, including the parts that make us look bad, because the alternative is the kind of evasive press release that makes you trust the industry less every time you read one. And we'd recommend, out of an abundance of caution, that anyone with a weak or reused master password rotate it. Not because the dump can be cracked — the math says it can't, in any reasonable timeframe — but because "in any reasonable timeframe" is a phrase that should always make a security person twitch.

    The honest summary

    If Pwdly's database leaked tomorrow, an attacker would walk away with a list of email addresses, an opaque graph of who-is-in-which-project, and a very large pile of ciphertext. The actual passwords, notes, custom fields, project names, and folder structures would remain encrypted under keys that have never touched our servers. That isn't a marketing claim; it's a property of the architecture. We don't have the keys. We can't be compelled to produce them. We can't accidentally email them to the wrong person at 4pm on a Friday.

    That's the bar. Build the thing so that the worst day for us is, at most, an inconvenient day for you. Then live up to that every day in between. If you want to pull the architecture apart yourself, the Security page is the source of truth, and it's deliberately written for people who, like us, want to verify rather than trust.

    #security#threat-model#zero-knowledge

    Related reading

    No cookies. No tracking. No banners (almost).

    We use privacy-friendly, cookieless analytics (Umami) to count page views — no personal data, no profiling, no third-party scripts. Read more.