ASIN Watcher
Security

How your account is protected

This page describes what is actually implemented, in enough detail that someone could check it. There is no certification to show you and no audit to cite, so what follows is the mechanism itself.

Passwords

Your password is never stored. What is stored is a PBKDF2-HMAC-SHA256 derivation of it: one hundred thousand iterations against a 32-byte random salt generated separately for every account, producing a 32-byte digest.

The per-account salt is why a stolen database cannot be attacked in bulk. A precomputed table has to be rebuilt for every account it is aimed at, which is the difference between cracking one password and cracking all of them at once. The comparison at sign-in is constant-time, so the check itself gives away nothing about how close a guess came.

This runs one way only. We cannot read your password, cannot recover it and cannot read it back to you over support. A forgotten password is reset, never retrieved. Reset links and email verification links are held the same way, hashed and never in the clear, so holding the database does not hand anyone a working link.

Sessions

Signing in issues a signed token good for fifteen minutes, and a refresh token good for thirty days. The short one is what every request carries, so a leaked token stops working quickly on its own.

The two are not interchangeable. Each carries a field declaring its type, and a refresh token presented where an access token belongs is rejected rather than quietly accepted.

Both point at a session record on the server, and that session is bound to the network address and the browser that created it, so a token lifted off one machine does not simply work from another. Changing your password ends every active session at once.

Failed sign-ins: a delay, not a lockout

The first three failed attempts on an account cost nothing. From the fourth, every further failure adds a wait that doubles, and stops doubling at five minutes. One correct sign-in resets the counter to zero.

The account is never locked. That is deliberate. Anyone who knows your email address could trigger a lockout on demand, and a policy that lets a stranger shut you out of your own account has traded one problem for a worse one. A growing delay makes guessing impractical without handing anyone that lever.

Requests are rate-limited more generally as well, counted per network address and per route requested. Adding a product is limited per account instead, and more tightly: ten a minute before you have verified your email address, fifty after.

Payments

Card numbers never reach our servers. The card fields and the authorisation belong to Stripe and PayPal; what comes back to us is a transaction reference. Our database has no column for a card number, a security code or a bank account, which is a firmer statement than a promise not to look.

The messages those providers send to confirm a payment are verified before they are believed. For one provider that means a signature recomputed here and compared in constant time, inside a 120-second window so an old message cannot be replayed; for the other it means a verification call back to the provider itself. Both paths cap the body at 64 KB, so an oversized payload cannot be used to exhaust the server.

Bitcoin and bank transfer are confirmed by a person. That is slower, and it involves no card data at all.

The rest of the surface

Responses carry the headers that stop a browser being talked into something: content-type sniffing off, framing denied, HTTPS pinned for a year including subdomains, a referrer policy that does not hand the full URL to other sites, and geolocation, microphone and camera switched off by policy. Anything carrying your account data is additionally marked never to be held by a cache in between.

This site sends a content security policy that defaults to its own origin, denies framing outright, and lets an inline script run only when its hash is listed. The one declared exception is the address the pricing page reads its figures from.

Attachments on support tickets are checked on more than their name: the extension has to be one of four, the size is capped at five megabytes, and the first bytes of the file must match the type it claims to be. The filename itself is cut back to its last component before anything is written, so it cannot point outside the upload directory.

Values you supply reach the database as bound parameters rather than as text pasted into a statement. Nothing in the web-facing code evaluates data as code, and TLS verification is never switched off to make a call succeed.

What we do not claim

We hold no security certification. We have not been audited by a third party. We are not going to print a compliance acronym on this page, because the ones that mean something require evidence we do not have, and the ones that mean nothing are worse than silence.

There is no uptime figure here either. Checks run periodically, the service can be interrupted for maintenance, and a number invented for a marketing page would be the least reliable thing on it.

All of the above describes the code as it stands today. It is not a guarantee that nothing is wrong with it. Nobody honest offers that, which is why the next section exists.

Reporting a problem

If you find a vulnerability, write to [email protected] with the word security in the subject line. The same address is published in machine-readable form at /.well-known/security.txt, where disclosure tools expect to find it, with English and Spanish both listed as reply languages.

A useful report says what you did, what happened, and what you expected instead. A URL, a request, and the account you used are usually enough. Screenshots help; a scanner's raw output usually does not.

Please test against your own account and stop at proof. Reading another person's data, deleting anything, or running load against the service turns a report we want into an incident we have to respond to.

Give us a reasonable window to fix the problem before you publish it, and tell us if you want credit when we do. This page was last reviewed on 15 August 2026.