nullcipher

Mask a whole file before you attach it to an AI chat

Drop a log, .env, JSON or HAR file. Keys, tokens, cookies, passwords and personal data become placeholders like [COOKIE_1] and you download a masked copy. The file is read in this tab and never uploaded, not even to us.

1 Choose or drop the file

2 Paste the AI's answer to get your values back

The mapping from the file you just masked stays in this page's memory until you close or reload the tab. It is not written to browser storage. After a reload, load the mapping file you downloaded to restore an answer.

Why a file, and why before the upload

Support desks and AI assistants increasingly ask for the whole file: a 40 MB application log, a .env to explain a startup error, or a HAR capture of a failing login. An AI chat cannot mask a file for you, because by the time it could read it, the file has already been sent. A HAR capture is the worst case: it records every request header, so it holds your live session cookies and Authorization: Bearer tokens, which are enough to sign in as you until they expire.

How a big file is masked without splitting a secret

The file is read in 4 MB slices and masked by a background worker, so the page stays responsive and the progress bar moves. A first quick pass only looks for text that already has the shape of a placeholder, such as [EMAIL_1], so the masker never issues one that is already in the file and un-masking can never change a line you did not mask. The second pass masks.

  • Text is masked in chunks of about 256 KB that end only at a line break. The partial last line is carried into the next chunk. A single line longer than a chunk, such as minified JSON, has to be cut inside the line, but never inside a value a rule has found, and the next chunk still sees the text before the cut.
  • If a -----BEGIN … PRIVATE KEY----- block has started but its END line has not arrived yet, the whole block is carried forward until it has, so a key is always hidden as one [PRIVATE_KEY_1].
  • Each chunk also sees the previous 2 KB of lines as context. A rule that needs a nearby word, such as a US Social Security number that is only masked when SSN stands within 40 characters before it, works across the chunk edge too.
  • One placeholder list covers the whole file: an address that appears on line 3 and line 900,000 is [EMAIL_1] both times, so the AI can still see it is the same person.

The same 229 detectors as the paste box run on every line: cloud and API keys (including 196 provider key formats ported from gitleaks), wallet recovery phrases, JWTs, private keys, bearer tokens, cookies, passwords in config lines and connection strings, e-mail addresses, phone numbers, IBANs, card numbers, eleven national ID numbers and IP addresses. Each rule, with what it deliberately leaves alone, is listed on the secret types page. On a sparse application log, the engine masks roughly 10 MB a second on one core of a typical server CPU; a phone is slower, and a log with a secret on every line is slower too.

What happens to a HAR file

A .har file, or a .json file that starts with {"log": the way browsers export a HAR, is masked by field as well as by pattern, because a session cookie called sid with a random value has no pattern to find:

  • request and response header values for Cookie (every value, names kept), Set-Cookie (the value, attributes kept), Authorization and Proxy-Authorization (the credential, the scheme kept), and any header whose name contains token, api-key, apikey, secret or session;
  • every request.cookies[].value and response.cookies[].value;
  • queryString[] and postData.params[] values whose name contains one of those words or password, credential or signature, and the same parameters inside request.url, redirectURL, Location and Referer headers, and a form-encoded postData.text;
  • every other string, including response bodies, through the same detectors as a text file.
"url": "…/v1/me?access_token=q8Zt…&lang=en"
  → "url": "…/v1/me?access_token=[SECRET_1]&lang=en"
{"name": "cookie", "value": "sid=8f3a9c…; theme=dark"}
  → {"name": "cookie", "value": "sid=[COOKIE_1]; theme=[COOKIE_2]"}
{"name": "authorization", "value": "Bearer eyJhbGciOi…"}
  → {"name": "authorization", "value": "Bearer [BEARER_1]"}

The same value keeps the same placeholder everywhere, so the token in the URL and in queryString are both [SECRET_1]. Only the text inside strings changes: the masked HAR is still valid JSON with the same structure, and it opens in a HAR viewer. A HAR file is read into memory whole, so a very large capture needs a browser with memory to spare; plain-text files are streamed.

The download and the mapping file

The masked copy is named after the original with .masked before the extension: app.log becomes app.masked.log, capture.har becomes capture.masked.har. The mapping is a separate JSON file listing each placeholder and the exact text it replaced. You only need it if the tab is closed before the AI's answer comes back: load it in step 2 and the answer restores exactly as it would have in this tab. For a UTF-8 file, un-masking the whole masked copy with its mapping gives back the original byte for byte; that is how this page is tested, on a 50 MB log and on a HAR capture.