Security, and how to check it yourself

The strongest security property this service has is architectural: for the browser tools, your file never reaches a server, so there is no server-side copy to breach. That is a claim you can verify in about 60 seconds with your own browser, and this page tells you exactly how.

The architecture, in one paragraph

The Excel, CSV, text, JSON and contacts tools are JavaScript that runs on your machine. Your browser reads the file with the File API, the dedupe engine runs in the page, and the download you get back is generated in the tab. There is no upload endpoint for those tools. Not a private one, not a rate limited one: the route does not exist. The engine modules themselves are structurally prevented from running on a server, and that is enforced by a test in the repository rather than by a convention: a server file that imported either engine fails the test suite.

The account layer is separate and small. It knows your email, your plan, hashes of your API keys, and one metadata row per job. The HTTP API is the only place data you send is processed on our infrastructure, and it processes it in memory and answers.

Verify the client-side claim in your own browser

Do not take our word for it. Two tests, both under a minute.

The network panel test

  1. Open the Excel tool in a fresh tab while signed out.
  2. Open DevTools and select the Network tab. Leave it recording.
  3. Drop in the largest file you are comfortable using. Run the dedupe. Download the result.
  4. Read the request list. You will see the page's own HTML, CSS, JavaScript, the two Google Fonts requests, and the SheetJS library from cdn.sheetjs.com. Every one of them is us sending code to you. Nothing goes the other way. Filter to Fetch/XHR for the fastest version of the same proof: signed out, that list stays empty for the whole run.

The airplane mode test

Better, because it cannot be faked by a request you missed. Load the tool page, then turn off your network connection entirely, then drop your file in and dedupe it. It still works. Software that was uploading your file could not do that.

What changes when you are signed in

One thing, and we would rather you find it here than in your network panel. When you are signed in, a completed browser job posts a metadata record so your dashboard has a history: file name, where it ran, match mode, the column names you matched on, the fuzzy threshold, rows in, rows kept, rows removed, and how long it took. It shows up as a single POST to the page's own URL, and you can read its payload in DevTools: it is a few hundred bytes whether your file had 500 rows or 500,000, because it contains counts rather than data. The fields map one for one onto the jobs table, which has no column that could hold a row of your file. Signed out, that request is not made at all.

What the server actually stores

Four tables. Users: email, plan, Stripe customer id, created date. API keys: a hash, a display prefix, a label, timestamps. Jobs: names, counts, timings. API usage: endpoint, mode, counts, billable units, HTTP status, duration.

The verification route is a button, not a promise. Export your account as JSON and read the file. It is a dump of every row we hold about you. Diff it against the schema if you like. There is no field in it that could contain a file, a row, or a cell value, because no table has one.

What happens to a request you POST to the API

The API is the one place you deliberately send us data, so it deserves precision:

It still runs on hosted infrastructure, and while it is in flight it exists in our function's memory and passes through our host's network. If that is unacceptable for a given dataset, use the browser tools instead, where it never happens at all.

API keys

Sessions

Transport and browser hardening

We do not currently ship a Content Security Policy. Assets come from two third party origins (the SheetJS library and Google Fonts), and a CSP that allowlists them without being tested against every page is decoration rather than a control. It is on the list. This page will say so when it lands, not before.

Third party code in the page

Two origins, both listed in the privacy policy: cdn.sheetjs.com for spreadsheet parsing, and Google Fonts for two typefaces. The SheetJS library parses your file in your browser; it is code we load, not a service we send anything to. If loading a library from a CDN is outside your threat model, the CSV, text and JSON tools do not load it at all.

What you should not trust us with

The useful half of a security page. All of the following is true of the API and the account layer; none of it applies to a browser tool used signed out, where nothing leaves your machine:

Nothing on this list is a reason not to use the free browser tools, which is where most of this site's work happens. It is a list of things not to route through a hosted endpoint operated by a small company, which is true of any small company, and more useful said out loud.

Reporting a vulnerability

Email support@dedupe.dev with "security" in the subject line. Please include what you found, the steps to reproduce it, and what an attacker could do with it. A proof of concept helps enormously.

Last updated