KeyFinder: a browser extension that watches pages for leaked keys
Passive API key and secret discovery browser extension for Chrome and Firefox. 80+ detection patterns, zero config.
At a glance
- What is it?
- KeyFinder is a Manifest V3 extension for Chrome and Firefox that passively scans the pages you visit for API keys, tokens and private keys, using more than 80 provider specific patterns plus entropy analysis. It is a live browsing scanner, not a repository scanner, and it stores what it finds in the browser.
- Who is it for?
- Adopt KeyFinder when you are auditing web applications as a bug bounty hunter or security engineer and want to spot keys exposed in front end code, script URLs, hidden fields or network responses while you browse. Do not adopt it as a repository secret scanner, since it only sees pages your browser loads and never inspects source history, and do not treat its findings as confirmed vulnerabilities until you validate them.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 97 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Ten surfaces of a page, scanned on every load
KeyFinder is a browser extension for Chrome and Firefox that scans every page you visit for leaked API keys, tokens, secrets and credentials, running silently in the background with what the README calls zero configuration.
What makes it more than a regular expression sweep of the DOM is the list of surfaces. It checks script src URLs for keywords and tokens in query parameters, scans script tag contents, fetches and scans same-origin JavaScript files, checks meta tags, inspects hidden input fields, scans data attributes, parses HTML comment nodes, analyses links and hrefs for tokens in query strings, reads localStorage and sessionStorage, and intercepts XHR and Fetch responses. Iframes and embedded content are covered too, and a MutationObserver re-scans dynamically injected DOM so single page applications are not missed.
That coverage is what makes it useful in a bug bounty context. A key left in a build artefact, a comment or a query string never appears in the rendered page, so a visual inspection of the site would miss it. The extension is aimed at whoever visits the page, which is why the topics list it under recon and secret detection rather than as an auditing platform.
Provider patterns rather than generic key hunting
The catalogue is the asset. The README states that KeyFinder ships with more than 80 detection patterns, and the table breaks them down by category with named providers.
Cloud coverage includes AWS access keys, secret keys, session tokens and Cognito, Google Cloud API keys, OAuth and service accounts, and Azure storage keys, SAS tokens and connection strings. Source control covers GitHub personal access tokens, OAuth and fine-grained tokens, GitLab personal access tokens, pipeline and runner tokens, and Bitbucket. Payments covers Stripe secret, publishable, restricted and webhook keys, PayPal Braintree and Square. Communication covers Slack bot, user and app tokens plus webhooks, Discord bot tokens and webhooks, Telegram, Twilio and SendGrid.
The AI and machine learning row lists OpenAI, Anthropic, HuggingFace and Replicate, which is a reminder that the pattern set was extended after the wave of model providers arrived. Databases cover MongoDB, PostgreSQL, MySQL and Redis connection strings, the SaaS row names Shopify, Sentry, New Relic, PlanetScale, Linear, Notion, Datadog, Algolia and Mapbox, and infrastructure covers HashiCorp Vault, Terraform, Docker Hub, NPM, Cloudflare, DigitalOcean, Doppler, Pulumi and Grafana. Crypto covers RSA, EC, OpenSSH, PGP and DSA private keys, and the generic row handles JWTs, Bearer tokens, Basic Auth, API key assignments, credential URLs and high-entropy strings.
Provider specific patterns are the difference between a match you can act on and a string that merely looks secret, which is where the entropy pass comes in.
Shannon entropy catches the formats nobody documented
Alongside the known patterns, the extension applies Shannon entropy analysis to detect random high-entropy strings that may be undocumented secret formats. This is the part of the design that generalises beyond the pattern list.
A pattern can only find what someone already thought to write down. If a company issues internal tokens in a format nobody has published, a pattern list misses them entirely, while an entropy heuristic notices that some unexplained base64-looking blob is far more random than the surrounding text. The cost of that approach is false positives, since encoded assets, hashes, build identifiers and compressed payloads all look random. The README does not document a threshold, a score or any way to tune the entropy pass, and it does not say how its results are separated from the pattern matches, so in practice you should expect to review the generic bucket by hand rather than trust it blindly.
The custom keyword feature is the manual complement. You can add your own search terms, validated, with a maximum of 50 of them, and they are used to scan script URLs, inline code and key-value assignments. The defaults are the obvious suspects: key, api_key, apikey, api-key, secret, token, access_token, auth, credential, password, client_id and client_secret.
A service worker, a content script and a MAIN world interceptor
The architecture block in the README shows how the extension is split, and one part of it deserves attention because it is unusual for an extension of this kind.
Most of the work happens in an ISOLATED world content script called content.js, which handles the DOM, scripts and network. Alongside it there is an interceptor-loader.js that sets a nonce and injects a MAIN world interceptor.js carrying the XHR and Fetch hooks and the window global scanning. background.js is the service worker handling storage and message handling, and results.js drives the findings dashboard with filtering and export. There are separate manifests, manifest.json for Chrome and manifest.firefox.json for Firefox, and the whole thing is plain vanilla JavaScript with no jQuery and no external libraries.
The MAIN world piece is what allows the extension to see responses and globals that an isolated content script cannot reach. The README calls the channel between the two worlds a hardened bridge using a per-page nonce on the CustomEvent channel, which is the standard way to stop other scripts on the page from reading or forging messages to the extension. That detail matters for a tool whose entire output is a list of secrets, since a page that could inject its own findings would poison your triage.
Storage is bounded and writes are serialised across tabs, with a 5000 finding cap and FIFO eviction, so the extension cannot grow without limit.
Installing from the stores, or loading it unpacked
The published route is a store listing, with a Chrome Web Store page and a Firefox Add-ons page, both linked from the README. The source route is a clone, and the README gives the exact command:
git clone https://github.com/momenbasel/keyFinder.gitFor Chrome, go to chrome://extensions, enable Developer mode, click Load unpacked and select the keyFinder folder. For Firefox, go to about:debugging, choose This Firefox, click Load Temporary Add-on and select manifest.firefox.json from the keyFinder folder. The separate Firefox manifest is why that one file is named explicitly, and Load Temporary Add-on means the add-on disappears when the browser restarts unless it is installed properly.
The folder layout you select is exactly the architecture block from the README:
keyFinder/
manifest.json # Chrome MV3 manifest
manifest.firefox.json # Firefox MV3 manifest
popup.html # Extension popup UI
results.html # Findings dashboard
js/
background.js # Service worker - storage and message handling
patterns.js # 80+ secret detection regex patterns
content.js # ISOLATED-world page scanner - DOM, scripts, network
interceptor-loader.js # ISOLATED loader - sets nonce, injects MAIN-world interceptor
interceptor.js # MAIN-world XHR/Fetch hooks + window global scanning
popup.js # Popup logic
results.js # Dashboard logic with filtering and export
css/
popup.css # Popup styles
results.css # Dashboard styles
icons/
icon16.png
icon48.pngThe source tree also holds css, icons, js, scripts, a store directory for the listing assets and a preview directory, with PRIVACY.md, SECURITY.md and a CHANGELOG.md at the top level. Those three files are the ones to read before installing anything that handles credentials.
Triage, export and the sanitiser that matters
The results dashboard is described as an ops-console style interface: findings sorted by severity, click to filter severity tiles, a latest-finding ticker and live search where the slash key focuses the field and Escape clears it. One-click triage lets you copy a secret straight from a match chip, with relative timestamps that show the absolute time on hover and a per-finding delete.
The export path is where a real risk lives. Findings can be downloaded as JSON or CSV, and the README notes the CSV export includes a formula injection sanitiser. That matters because spreadsheet applications treat a leading equals sign or plus sign as a formula, so a CSV containing attacker-controlled strings can execute when a triager opens it in Excel. If you are the author of a similar tool, that sanitiser is the detail to copy.
Other pieces of the design are worth knowing. A red-dot icon overlay marks tabs that have findings, the extension is described as having a low CPU and memory footprint, and a per-tab alert badge tells you which tab to look at. Custom keywords are validated and capped at 50.
One boundary is worth stating plainly. This is a passive scanner for pages you visit. It does not validate a key, does not test it against the provider's API, and does not tell you whether a credential is still live. A finding is a prompt to investigate, not a confirmed vulnerability, and a report built on it needs that validation step done by hand.
Version 2.2.1, an MIT licence and a passive by design tool
The project ships regularly. The recent releases are v2.2.1 on 2026-07-18, v2.2.0 on the same day and v2.1.1 on 2026-05-14, and the last push to the repository was on 2026-07-19. Two releases on one day is a sign of an active release flow rather than a slow moving project.
The licence is MIT, so the code can be read, modified and redistributed with the notice retained, and the store listings are the supported distribution path for people who do not want to build it.
Where this tool sits is best understood by contrasting it with the other way to find leaked secrets. A repository scanner works on source code and its history, and finds keys committed to a project. KeyFinder works on rendered pages, and finds keys that were never committed anywhere: shipped in a bundle, embedded in a script URL, left in a comment, returned in an API response, or cached in web storage. The two approaches catch different sets of the same problem, and the browser approach is the one that reaches keys that only ever existed in production.
The constraint that follows from the design is that coverage equals your own browsing. A secret on a page you never visit, on a domain you do not open during an engagement, or behind a login you never perform is not going to appear in the findings list.
Editorial conclusion
Adopt KeyFinder when you are auditing web applications as a bug bounty hunter or security engineer and want to spot keys exposed in front end code, script URLs, hidden fields or network responses while you browse. Do not adopt it as a repository secret scanner, since it only sees pages your browser loads and never inspects source history, and do not treat its findings as confirmed vulnerabilities until you validate them. Verify first that the version you install matches the current release, that the export you plan to share has been through the formula injection sanitiser, and that your own machine is not the one storing 5000 findings of unencrypted credentials in browser storage.
Frequently asked questions
What does KeyFinder detect?
KeyFinder ships with more than 80 detection patterns covering cloud providers, source control, payment, messaging, AI and machine learning providers, databases, SaaS, infrastructure and private keys, plus generic JWTs, Bearer tokens, Basic Auth and high-entropy strings. It scans ten surfaces of every page, including script URLs, inline scripts, meta tags, hidden fields, data attributes, HTML comments, URL parameters, web storage and XHR and Fetch responses.
How do I install KeyFinder on Chrome or Firefox?
It is published on the Chrome Web Store and on Firefox Add-ons. From source, clone the repository, then in Chrome enable Developer mode at chrome://extensions and choose Load unpacked with the keyFinder folder. In Firefox open about:debugging, pick This Firefox, click Load Temporary Add-on and select manifest.firefox.json.
Does KeyFinder validate the keys it finds?
No. It is a passive scanner that reports what appears in page content, so a finding is a prompt to investigate rather than a confirmed vulnerability. Nothing in the README describes testing a discovered credential against the provider.
What happens to the findings KeyFinder collects?
They are stored in the browser, with a cap of 5000 findings and FIFO eviction, and writes are serialised across tabs. You can delete findings individually, and export the filtered list as JSON or CSV, with the CSV export passing through a formula injection sanitiser.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/momenbasel-keyfinder)Was this useful?