Lintroller

Privacy: what runs where

Your file is read by this page, in your browser. It is not uploaded anywhere.

ThingWhere it goes
Your CSVRead in this tab by a background worker on your device. Never sent anywhere.
Findings and evidenceShown in this tab. Gone when you close it, unless you turn on Remember on this device.
Cancel linksOpen the company's own page in a new tab, only when you click one.
Downloads (CSV, .ics)Saved by your browser to your device.
Analytics, error reports, cookies, accountsNone.

What is stored, and where

  • By default: nothing. Refreshing the page clears your review.
  • With Remember on this device: one entry in this browser's local storage, named subsweep:v1, holding your choices and the findings list. Delete everything removes it.
  • No cookies, no IndexedDB, no session storage, no service worker.

The rule the browser enforces

This is the Content Security Policy sent with each page. connect-src 'none' means the page cannot send anything to a server after it loads: the browser blocks scripted requests, beacons and live connections.

default-src 'none'; script-src 'self'; worker-src 'self'; connect-src 'none'; img-src 'self' data: blob:; style-src 'self'; font-src 'self'; manifest-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; object-src 'none'; upgrade-insecure-requests

Check it yourself

  1. Open your browser's developer tools and go to the Network tab.
  2. Drop in a file, or use the sample file.
  3. Nothing new appears in the Network list, and there is no request with your rows in it.
  4. Storage shows nothing for this site unless you turned on Remember on this device.

Published proof

Status: passed 32 of 32 checks on lintroller.vercel.app, run Oct 5, 2026.

  • flow walked with the canary file: import, review (confirm 2, dismiss 1), summary: pass (Read 132 rows from 1 file. 5 charges look like they repeat. confirmed Quokka Streaming; confirmed Zebrafish Gym; dismissed Apple subscription; Confirmed: $1,866.48 a year. Not yet reviewed: $329.76 a year.)
  • flow walked with the second file: import, review (confirm 2, dismiss 1), summary: pass (Read 132 rows from 1 file. 5 charges look like they repeat. confirmed Pelican News; confirmed Otter Climbing; dismissed Apple subscription; Confirmed: $562.80 a year. Not yet reviewed: $329.76 a year.)
  • zero requests after the initial page load, other than the cancel-link clicks: pass (canary: 2 after load (4 during load), second: 2)
  • each cancel-link click: one navigation, aborted, on the clicked entry's domains: pass (4/4: netflix → help.netflix.com, spotify → support.spotify.com)
  • no request to any other host, the initial load included (no fonts, scripts, analytics, beacons): pass (4 outside requests, all cancel-link clicks)
  • no canary token (QUOKKA, ZEBRAFISH, 7781, 77.77) in any request URL, header or body: pass
  • all requests are GETs with no body: pass (0 others)
  • request list to our origin is identical for a second, different file: pass (4 requests: GET /, GET /assets/index-LFqt1INo.js, GET /assets/index-BavcVC0c.css, GET /assets/engine.worker-DV3690aV.js)
  • CSV and ICS are built in the browser and saved from blob: URLs: pass (CSV 1014 chars, ICS 2434 chars)
  • before the opt-in: no cookies, local/session storage and IndexedDB empty: pass ({"local":[],"session":[],"idb":[]})
  • after "Remember on this device": exactly one key, subsweep:v1: pass ({"local":["subsweep:v1"],"session":[],"idb":[]})
  • after "Delete everything": storage empty, no cookies: pass ({"local":[],"session":[],"idb":[]})
  • no service worker registered: pass
  • 0 securitypolicyviolation events during the flow: pass
  • CSP enforced: a request to /x made by script in the page is blocked and reported (connect-src 'none'): pass (probe → blocked; violations: connect-src https://lintroller.vercel.app/x; requests sent: 0)
  • no console errors: pass
  • offline after the first load: import, review, summary, CSV and ICS still work: pass (Read 132 rows from 1 file. 5 charges look like they repeat.; 0 requests attempted while offline)
  • exact SPEC §10 headers on /: pass (HTTP 200)
  • exact SPEC §10 headers on /sweep: pass (HTTP 200)
  • exact SPEC §10 headers on /sweep/review: pass (HTTP 200)
  • exact SPEC §10 headers on /sweep/summary: pass (HTTP 200)
  • exact SPEC §10 headers on /how-to-export: pass (HTTP 200)
  • exact SPEC §10 headers on /privacy: pass (HTTP 200)
  • exact SPEC §10 headers on /about: pass (HTTP 200)
  • exact SPEC §10 headers on /privacy-results.json: pass (HTTP 200)
  • exact SPEC §10 headers on /robots.txt: pass (HTTP 200)
  • exact SPEC §10 headers on /favicon.svg: pass (HTTP 200)
  • exact SPEC §10 headers on /og.png: pass (HTTP 200)
  • exact SPEC §10 headers on /sample/sample-statement.csv: pass (HTTP 200)
  • exact SPEC §10 headers on /assets/index-LFqt1INo.js: pass (HTTP 200)
  • exact SPEC §10 headers on /assets/index-BavcVC0c.css: pass (HTTP 200)
  • exact SPEC §10 headers on /assets/engine.worker-DV3690aV.js: pass (HTTP 200)

Cancel links were last checked Oct 4, 2026.