Frequently asked questions
Click any question to expand it. Each one has its own link, so you can share a direct answer - right-click the question and copy its link, or copy the page's address once it's open.
Does my code get uploaded anywhere?
No, not with either version. The online scanner
runs entirely in your browser - scanning, redaction, and the
sanitized download are all produced client-side, and nothing is
sent to a server (that's what the "Runs in your browser — nothing
uploaded" badge on the scanner page means literally). The desktop
app is a small local web server on your own machine
(http://127.0.0.1:5057) with no network calls -
everything runs locally, and no data leaves that machine. The
page itself loads its fonts and the zip library from Google
Fonts and cdnjs, so those hosts can see that you visited - but
the files you're scanning are never sent anywhere.
Why does Windows say the desktop app is unrecognized or block it entirely?
The .exe is unsigned - code-signing certificates cost
money and aren't practical for a small open-source project to
maintain. Two different things can happen as a result:
- Windows SmartScreen shows a dismissible "unrecognized publisher" or "Windows protected your PC" warning. This is expected for new, unsigned software and isn't by itself a sign anything is wrong - you can choose to run it anyway after verifying the checksum (see the next question).
- Smart App Control, or a managed Application Control (WDAC/AppLocker) policy on a company-managed machine, can block the executable outright, with no "Run anyway" option. This is a stricter, non-dismissible response that signing or a new release can't fix. If this happens, use the online scanner instead (no download at all), or build the app yourself from source.
How do I verify my download is genuine?
Check its SHA-256 checksum against the value published in that specific release's notes on the GitHub Releases page.
On Windows:
certutil -hashfile CredentialScrubber.exe SHA256
On Mac/Linux:
shasum -a 256 CredentialScrubber.exe
If the output doesn't match the checksum published for that release, don't run the file - re-download it, and if it still doesn't match, open an issue.
What does clicking "Ignore" on a finding actually do?
It restores the original, unmasked value in the working copy, since that's the only way to stop the tool flagging something you've confirmed isn't a real secret. Because of that, it asks for confirmation first, and it can always be undone afterward from the "Ignored findings" list (restoring the mask). Nothing is downloadable yet at that point, either way - the scanner's download flow is a separate, deliberate "Generate sanitized file" step that only becomes available after you click it, and any further change (another ignore, a restore, a re-scan) marks that generated copy stale until you regenerate it.
Which languages and file types does it check?
Full detection (variable/key names and value
patterns): Java, Python, JavaScript/TypeScript, Go, and C# source
code, plus these config formats: .properties,
.yml/.yaml, .json,
.xml, .config, .ini,
.conf, .cfg, and .env.
Multi-line split-string detection (a secret
built up across several lines): Python's parenthesized-string
style, and Java/JavaScript-TypeScript/C#/Go's
+-operator style. Not covered: a
JavaScript/TypeScript template literal that spans multiple
lines.
Any other file type (a lockfile,
Dockerfile, .rb script, README, etc. -
neither extension/filename is recognized): both products now
behave the same way, scanning it for a small set of
high-confidence secret shapes only - AWS access keys,
GitHub/Slack tokens, JWTs, private-key blocks, and URLs with
embedded credentials - with no key-name matching at all. We
tested a .rb file containing a plain
password = "..." assignment and an AWS-style access
key, and a Dockerfile setting an env var to a
password value: both products caught the AWS-style key (its
shape is recognizable on its own) but not the
plain password = "..." assignment or the
Dockerfile's env var, since neither value looks like a
recognizable secret shape by itself - that detection relies on
key-name awareness that only exists for the file types listed
under "Full detection" above. A broader set of shapes (plain IP
addresses, generic URLs, email addresses) was deliberately left
out of this fallback after testing it against a realistic
project full of lockfiles and docs and finding it was almost
entirely false positives - gem/package version numbers read as
IP addresses, lockfile registry URLs, and ordinary contact
emails.
A real, multi-line private-key block (id_rsa,
server.pem, or one pasted as-is into any other
unrecognized file type) is also caught - matching
-----BEGIN/-----END ... PRIVATE KEY-----
markers across lines, masking the body while leaving the harmless
BEGIN/END lines themselves and a -----BEGIN
CERTIFICATE----- block (not a secret) untouched. A block
only starts at a line that's just the BEGIN marker
(leading whitespace/one optional quote character allowed, never
mid-sentence) - a document that merely mentions the marker is
left untouched. When no END line follows, only the consecutive
lines that still look like key material (base64 body text, or a
Proc-Type:/DEK-Info: header) are
masked, stopping at the first line that doesn't, so a marker
mentioned in passing and then followed by ordinary prose doesn't
lose that prose. This is separate from the single-line-only
value-pattern match above, and only applies to unrecognized
file types - a key embedded as a YAML block-scalar value, or
split across .properties continuation lines, in a
fully-detected file type is not caught by this
or any other existing mechanism.
Files recognized as binary, or over a 2MB size limit, are still skipped and copied through untouched either way - the scan results (and, on the desktop app, the Apply confirmation) list how many files this applied to and why.
For any language or file type outside full detection, review the output yourself before sharing it - don't assume it's been fully cleaned.
Why might a secret not be found?
Detection is pattern-based, not a full understanding of your
code: it matches key names (like password or
api_key), shapes of known secret formats (AWS/GitHub/
Slack-style tokens, JWTs, connection strings, and similar), and -
in config files and multi-line string concatenation only, not
single-line code - a general high-entropy check. There are
documented gaps, such as JavaScript template literals that span
multiple lines, which aren't covered. This is a detection aid, not
a guarantee that every possible secret shape is caught.
I found a real secret in my results - what now?
Rotate it. Masking a credential for sharing doesn't undo the fact that it existed in your code, possibly in a git history, a backup, or somewhere else you've already shared it. Treat any real finding as compromised and issue a new one.
Which browsers does the online scanner work in?
The core flow - selecting a folder, scanning, reviewing results, and downloading the sanitized copy - has been verified working identically across Chromium, Firefox, and WebKit (the engine behind Safari), with no page errors and a correctly redacted download in all three.
One feature is Chromium-only (Chrome/Edge and similar): "Remember a folder for next time," which uses the File System Access API. It's feature-detected and simply hidden - not broken - in browsers that don't support it; the drag-and-drop/"Choose folder" flow works the same everywhere either way.
Where is my scan history stored?
In the online scanner, scan history, the ignore list, and any rule edits are stored only in that one browser, on that one device (via IndexedDB) - nothing syncs across browsers or devices, and it's lost if you clear that site's browser data. Ignored values are kept as a one-way hash, never the real value, so a changed value always reappears flagged rather than staying silently hidden.
In the desktop app, scan history is kept in a local SQLite database in your OS's per-user application-data directory, so it persists across restarts on that machine.
Online scanner vs. desktop app - what's the difference?
Both use the same detection engine and both run entirely locally. The main differences:
- Install: the online scanner needs nothing -
open it in a browser. The desktop app is a Windows
.exe, or can be run from source on Mac/Linux. - Output: the online scanner produces a
downloadable
.zipvia an explicit "Generate" step. The desktop app writes the sanitized copy directly to an output folder you choose (after a preview step). - Git changed-files mode: only the desktop app has it (scan just what's changed in a git repo, not the whole project every time). The online scanner always does a full pass.
- History persistence: the desktop app's history survives restarts via a local database; the online scanner's is per-browser and lost if that browser's site data is cleared.
What license is this under?
The detection engine and desktop app are licensed under the GNU Affero General Public License v3.0 (AGPLv3). Free to use, modify, and redistribute under its terms - see the LICENSE file for the full legal text.
How do I report a bug, or a security issue?
For a regular bug or a question, open a GitHub issue - both the bug report and question forms require confirming you've replaced any real secrets with fake values first.
For a security vulnerability, use the private security advisory form instead of a public issue - see the "Still stuck?" section below for why that distinction matters.
Still stuck?
Open a GitHub issue - choose the bug report or question form.
Never paste real secrets, passwords, keys, tokens, or internal hostnames into an issue. GitHub issues are public. Use fake, obviously-made-up values to describe what happened.
Found a security vulnerability instead? Report it privately via a GitHub security advisory - not a public issue.