Skip to content

How this is built, and how to tell us if it is wrong

A short, specific account of how the service is secured — written for a reader who has to justify a supplier to their IT department, and who will not be satisfied by the words "bank-grade encryption".

Last updated

How signing in works

We email a six-digit code, and there is no password. Codes rather than magic links, for a specific reason: corporate mail scanners pre-fetch every URL in an incoming message, which burns a one-time login link before the recipient sees it. A code cannot be consumed by a scanner, because reading it is not using it.

  • Codes expire in 10 minutes, are single-use, and requesting a new one retires the old one, so only ever one code can open an account.
  • Five wrong attempts destroy the code. Six digits is a million possibilities; five guesses is a one-in-two-hundred-thousand chance, and unlimited guesses is a certainty.
  • Codes are stored as a keyed HMAC with a server-side secret, not a bare hash. A plain SHA-256 of a six-digit code can be reversed by trying all million; the key means a leak of the database alone is not enough.
  • Requests per address are rate limited, so the endpoint cannot be used to mail-bomb someone using our domain.

Sessions

A signed-in browser holds a 256-bit random token; we store only its SHA-256. The cookie is HttpOnly, so no script can read it, Secure in production, and SameSite=Lax so it is not sent on a cross-site POST. Sessions last 30 days and you can end all of them from your account page.

The application

  • Every state-changing request needs both a matching Origin header and a double-submit token. Three independent layers, because one is a single point of failure.
  • The Content-Security-Policy names no external script or style host. The only page that loads a third-party script is the checkout page, and its policy is widened to exactly Paddle's domains and nothing else.
  • The app renders on the server and its forms work without JavaScript, which also means there is no large client-side attack surface to audit.
  • The database role the app uses cannot write to the ingested data. A bug in a page cannot damage a corpus that took hours to load.
  • Payment webhooks are verified by HMAC over the raw request body, with a replay window, and are refused outright if the signing secret is not configured.

What we hold, and what we cannot lose

We never see card details — Paddle handles the payment. We hold no passwords, because there are none. We hold no raw IP addresses. The most sensitive thing in our database is a list of email addresses and the product codes each one watches, and the privacy page lists everything.

Reporting something

Email hello@devicesignal.com with "security" in the subject. We will acknowledge within one working day and tell you what we are doing about it.

We will not threaten you, and we will not ask you to sign anything before we listen. If you found something real, we will credit you unless you would rather we did not. Please do not run automated scans against the live service or access data belonging to anyone else — if you need an account to test with, ask and we will make you one.