KeyHound is a local, privacy‑first secret detector for VS Code. It scans your files as you work and flags likely credentials (API tokens, keys, webhooks, connection strings) before they escape your editor.
This repository contains the VS Code extension, its scanning engine, and a small catalog of detection rules.
- Fast, incremental scans of the current file and the workspace
- Built‑in rules for common providers (AWS, Slack, GitHub, Stripe, Google, MongoDB, npm, Twilio, …)
- Optional entropy‑based detection for generic high‑entropy tokens
- Inline suppressions and workspace ignores
- Findings panel with quick actions (ignore, redact, export)
- Local only — no telemetry and no network calls during scanning
- Install dependencies:
npm install - Build the extension:
npm run compile && npm run build:webview - Launch in VS Code:
- Open this folder in VS Code
- Press F5 to start an Extension Development Host
- In the Dev Host, open the sample test data under
testing/or@testing/ - Run “KeyHound: Scan Workspace” or “KeyHound: Scan Current File” from the Command Palette
Packaging a .vsix for local install:
npm run package:vsix(requires@vscode/vscewhich is indevDependencies).
KeyHound: Scan Current File— scan the active editorKeyHound: Scan Workspace— scan all files (excludes common build folders)KeyHound: Scan Git Diff— scan only lines changed vs.HEADKeyHound: Open Findings Panel— open the panel view of all current findingsKeyHound: Toggle Entropy Rule— enable/disable entropy‑based rule globallyKeyHound: Ignore Rule (workspace)— add rule to.keyhoundignoreKeyHound: Ignore Path— add a path pattern to.keyhoundignoreKeyHound: Ignore Rule (file)— ignore a rule for a specific pathKeyHound: Redact Occurrence— replace a match with a placeholder
Open via “KeyHound: Open Findings Panel”. From the panel you can:
- Insert an inline ignore next to a specific match
- Ignore a rule globally or for a single file pattern
- Redact an occurrence in place
- Export all current findings as JSON or CSV
KeyHound supports three layers of suppression:
-
Inline suppressions (within a file)
- Single line:
keyhound-ignore: <ruleId>[, <ruleId>…]- Applies to the same line and also to the following line (convenience for comment‑above style)
- Example:
const token = "..."; // keyhound-ignore: slack.bot_token - Multiple occurrences on the same line are supported:
// keyhound-ignore: generic.high_entropy // keyhound-ignore: slack.bot_token
- Block: surround a region with:
keyhound-ignore-start: <ruleId>[, …]keyhound-ignore-end
- Single line:
-
Workspace ignores (
.keyhoundignoreat the repo root)rule: <ruleId>— ignore a rule across the workspacerule: <ruleId> -> <glob>— ignore a rule for matching pathspath: <glob>— ignore matching paths regardless of rule- Globs are matched with
picomatch(dotfiles included).
-
Settings
KeyHound: Toggle Entropy Rulequickly disables the generic entropy rule.
If inline ignore comments are added/removed, KeyHound performs a full file rescan so findings reappear/disappear immediately.
Rules live under rules/ and use JSONC (JSON with comments). Each rule conforms to src/config/schema.ts and one of three methods:
regex— standard global regex match- Example (AWS Access Key ID):
prefix— find tokens that start with one of the configured prefixes and extend through token characters- Example (AWS Secret Access Key env lines):
{ "id": "aws.secret_access_key", "name": "AWS Secret Access Key", "method": "prefix", "prefixes": ["AWS_SECRET_ACCESS_KEY=", "aws_secret_access_key=\t"], "severity": "high", "confidence": "medium" }
- Example (AWS Secret Access Key env lines):
entropy— detect long, base64/hex‑ish strings above a Shannon entropy threshold
Additional examples are provided for GitHub, GitLab, Stripe, Google, Slack webhook, npm, Twilio, and MongoDB connection strings.
Redaction placeholder
- When using the “Redact Occurrence” action, the replacement text is derived from the rule’s
redactfield and the matched value (seesrc/redact.ts).
User/workspace settings (settings.json):
keyhound.enableEntropyRule(boolean, default:true) — enable/disable the generic entropy rule
Internal defaults (see src/config/defaultConfig.ts):
entropyThreshold: 4.5ignorePatterns: ["**/fixtures/**", "docs/code/*"](used by future config)
Two directories provide quick, manual validation data:
@testing/— one compact sample per rule; ideal for a quick smoke test
Run “KeyHound: Scan Workspace” in the Extension Development Host to see findings from both.
- Rules are loaded from
rules/and watched for changes (src/scanner/rulesLoader.ts) - Scans run on document open/change and on explicit commands (
src/extension.ts) - Incremental scanning:
- When a file changes, only the changed ranges are rescanned for speed
- Findings outside changed ranges are preserved, re‑validated against ignores, and deduplicated
- Any change touching inline ignore markers triggers a full‑file rescan
- Diagnostics are published per VS Code URI (
src/diagnostics/publish.ts) - Only real files are scanned — virtual documents like Git diffs are ignored to avoid duplicates
Performance
- The scanner operates under a small per‑scan time budget (default ~20ms per design notes) and dedupes results.
Privacy
- KeyHound runs locally in your editor. No findings or file contents are sent anywhere.
- Build:
npm run compile - Watch (TypeScript):
npm run watch - Lint:
npm run lint - Build webview bundle:
npm run build:webview - Package VSIX:
npm run package:vsix
Project layout:
src/— extension entry (extension.ts), scanning engine, diagnostics, UI panelrules/— detection rules (JSONC)@testing/— sample data used for manual validationwebview/— small UI to view/export findings
- Add new rules under
rules/using JSONC and include a short sample in@testing/ - Follow naming:
<provider>.<type>foridand title‑case forname - Keep regexes as specific and anchored as feasible to reduce noise
- Prefer
confidence: mediumorhighfor precise rules; uselowsparingly
If you have a Gitleaks/Kingfisher rule you’d like ported, open an issue or PR with references. We plan to add a converter for common rule formats.
- “Problems shows entries for .git virtual files” — ensure you’re on a build that ignores non‑file URIs (we skip
git:scheme). - “Inline ignore removed but finding didn’t reappear” — the current build forces a full rescan when ignore markers are added/removed; try saving the file once. If it persists, file an issue with a minimal example.
- “Too many entropy findings” — run
KeyHound: Toggle Entropy Ruleto disable, or add inline ignores for specific lines.
- Rule packs and auto‑update
- First‑class support for more providers
- CLI for CI usage (sharing the same engine)
- Richer config surface (enable/disable by tag, per‑folder thresholds)
{ "id": "aws.access_key", "name": "AWS Access Key ID", "method": "regex", "pattern": "AKIA[0-9A-Z]{16}", "severity": "high", "confidence": "high", "redact": "AWS_ACCESS_KEY_ID" }