What We Check When We Audit
We ran a full security review of the ResetKit API. It turned up work, we did the work, and the fixes went out the same night. Every one of them is covered by a test that fails if the behaviour ever comes back.
This post is about how we approach that, not about what was in it. The reason for that distinction is at the bottom, and it is not evasion.
What gets reviewed
The point of a review is to check the things that are actually load bearing, not the things that are easy to check. For an authentication service the list runs roughly:
Can one account reach another account's data? Every route that takes an identifier gets read with the assumption that the caller is lying about who they are. A valid session for one customer must never resolve to another customer's records, no matter what identifier is in the path.
Can input reach a query as anything other than a value? Every field that ends up near a database gets checked for whether it can arrive as something other than plain text.
Can a request be forged from somewhere else? Every operation that changes state gets checked for the token that proves the request came from where it claims. We pay particular attention to anything that changes an email address, because an email change plus a password reset is a complete account takeover in two steps.
Can a guess be repeated? Anything that accepts a code, a password, or a key needs a ceiling on attempts, and it needs to hold when the thing that enforces it is unavailable rather than falling open.
Does a failure message say too much? A login that distinguishes "no such account" from "wrong password" hands over a list of who has an account. Failures should be uninformative in a specific and deliberate way.
Where does the service make requests on someone else's behalf? Anywhere a customer supplies a destination, that destination has to be checked, and checked again at the moment of use rather than only when it was saved.
What is in the logs? Logs get copied into places nobody is thinking carefully about, and they outlive the systems that wrote them. Anything sensitive in a log line is sensitive forever.
What did we install? Every dependency is code we ship without having read. That inventory currently reports zero known vulnerabilities, and we intend to keep it there.
Two things we hold ourselves to
A check that is not tested is a wish. It is easy to write validation, watch it reject the obvious bad case, and move on. The bad cases that matter are never the obvious ones, and validation quietly stops working when someone refactors around it. So every property we rely on has a test that asserts the bad input is refused, including the awkward variants. Those tests are the actual security control. The code is just what makes them pass today.
Checking once is checking at the wrong time. A lot of security work validates something when it is first supplied and then trusts it forever. The world moves between those two moments. Where something can change between when it was approved and when it is used, we check it again at the point of use.
Why we do not list findings
We are not going to publish a description of each issue, and we want to say plainly why, because "we take security seriously" with no detail is exactly what a company says when it is hiding something.
Two reasons.
A specific description of a weakness is useful to someone attacking a service well beyond ours. Much of this work is not unique to us. Publishing a precise account of a class of mistake, along with how it presented, is a contribution to somebody's afternoon that we would rather not make.
And a public list of what we recently fixed is a strong hint about where to keep pushing. It tells you what kind of thing we get wrong, which parts of the system are newest, and where to spend an attacker's limited attention.
What we will commit to instead is more useful than a list: if we ever find that customer data was actually exposed, you will hear it from us directly and quickly, with specifics, whether or not anyone else would ever have known. That is the disclosure that matters. A changelog of internal fixes is not.
If you find something
Email support@resetkit.dev and put "security" in the subject. It reaches a person.
You do not need a proof of concept and you do not need to be sure. A vague report about something that felt wrong is worth sending. We would much rather read ten notes about nothing than miss the one that was something.
We will not send you a legal threat for telling us about a problem. That should not need saying, and it does.