
Secret Sentinel
io.github.AleBrito124356由 GitHub 账号 AleBrito124356 发布v0.3.0更新于 Nov 2, 2026
Local secret guardrails: scan code, git changes and MCP configs for API keys; redact text
概览
本地密钥扫描器,让助手在代码、git 变更和 MCP 配置中发现 API 密钥、令牌和私钥,并在泄露前进行脱敏。
- 可以做什么
- 扫描原始文本、单个文件或整个目录中的密钥,在仓库内按 git 规则列出文件
- 检查下一次提交或推送将发布的内容,并查看近期提交或所有分支新增的行
- 审计 MCP 客户端与 agent 配置文件,标出被 git 跟踪的文件,可选检查会话记录
- 对文本中的密钥进行脱敏,替换为带检测器名称的标记
- 列出启用的检测器、严重级别、修复建议和允许列表规则
- 适用场景
- 适合 AI 编码助手在代码仓库中工作时使用,在密钥进入提交、提示词、工具输出或 MCP 配置文件之前提供本地检查点。也适合在分享日志或输出前做清理。
- 运行要求
- 以 stdio 本地运行,通过 uvx 从 PyPI 包 mcp-secret-sentinel 启动,需要 Python 3.10 及以上。无需账号、API 密钥或网络访问。可选的 agent 钩子和 git pre-commit 钩子需通过命令行另行安装。
安装
在 SourceWeft 中
- 打开 控制台中的 Secret Sentinel,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
mcp-secret-sentinel
[tests] [Python 3.10+] [MCP SDK 1.x | 2.x] [License: MIT]
Local secret guardrails for AI coding agents. An MCP server, a CLI and agent hooks that catch API keys, tokens, private keys and passwords in code, commits, prompts, tool calls and MCP configs, before they leave the machine. 64 detectors, base64-aware, every finding redacted. No account, no network calls.
Secrets rarely leak through hackers; they leak through commits, and now through agents. GitGuardian's State of Secrets Sprawl 2026 counted 28.65 million new secrets on public GitHub in 2025 (+34%), AI-service keys up 81%, 24,008 unique secrets in MCP configuration files, and a higher leak rate in commits co-written with AI coding assistants. A key pasted into .mcp.json, echoed by cat .env into a transcript, or written into a config by an agent in a hurry is compromised from that moment, even if the next commit deletes it.
Secret Sentinel puts a checkpoint at each of those moments:
The full secret value never appears in any output, so it never enters the conversation transcript either.
Install
Claude Code plugin (skill + agent hooks + MCP server in one step):
The hooks run straight from the plugin checkout with any Python 3.10+ (they use only the standard library). The MCP server starts with uv.
MCP server only (any MCP client):
CLI (git hooks, CI, scripts): pipx install mcp-secret-sentinel or pip install mcp-secret-sentinel. To run the latest code from GitHub instead of PyPI, use uvx --from git+https://github.com/AleBrito124356/mcp-secret-sentinel mcp-secret-sentinel.
Agent skill only (Agensi, skills.sh, any agent that reads SKILL.md): the skill lives in skills/secret-sentinel. It tells the agent when to scan, how to fix a finding and how to rotate a leaked credential, and uses the MCP tools or the CLI when they are available.
Agent hooks
mcp-secret-sentinel hook reads one hook event as JSON on stdin and prints the agent's decision. The plugin wires it up for you; without the plugin:
The installer merges into the existing settings and keeps every other hook. Running it again refreshes its own entries instead of duplicating them.
By default the hook blocks high and critical findings and lets medium ones (JWTs, high-entropy strings) through; hook --fail-on medium is stricter. Excluded paths in .secret-sentinel.toml are respected. The event is read as UTF-8 whatever the console code page, so accented project paths work on Windows. Anything unexpected (bad JSON, a broken config, an internal error) fails open with a non-blocking exit status, so the hook can never wedge the agent; a git failure other than "not a repository" keeps scanning on. Our own MCP tools are exempt, since they receive secrets on purpose.
MCP tools
Every tool is annotated read-only (readOnlyHint, no open-world access), so clients can run them without a confirmation prompt. The scan tools publish an outputSchema and return structuredContent (MCP SDK 1.10+ / 2.x). The server also offers three prompts, pre_push_check, leak_response and audit_agent_configs, and a secret-sentinel://patterns resource.
All scan tools return the same shape:
suppressed is added when inline comments silenced findings, baselined when the baseline accepted some. Bounded responses: every scan lists at most max_findings findings (default 200, most severe first, 0 = no limit). When it has to cut, the report says truncated: true and keeps total_findings, counts_by_severity, counts_by_pattern and top_files, so a noisy tree cannot flood the agent's context.
Auditing agent and MCP client configs
scan_agent_configs (CLI: mcp-secret-sentinel agents [PROJECT]) checks:
- Project files:
.mcp.json,.claude/settings.json,.claude/settings.local.json,.cursor/mcp.json,.vscode/mcp.json,.vscode/settings.json,.gemini/settings.json,.codex/config.toml,.windsurf/mcp.json,.amazonq/mcp.json,.kiro/settings/mcp.json,.roo/mcp.json,opencode.json, and the agent instruction filesCLAUDE.md,CLAUDE.local.md,AGENTS.md,GEMINI.md,.cursorrules,.windsurfrules,.github/copilot-instructions.md. Each one reports whether git tracks it. - User files: Claude Code (
~/.claude.json,~/.claude/settings.json,~/.claude/CLAUDE.md), Claude Desktop, Cursor, VS Code, Cline, Windsurf, Gemini CLI, Codex, Amazon Q, Kiro, Continue, Zed, opencode, Goose and LM Studio. - Session transcripts (opt-in): the newest Claude Code and Codex
*.jsonllogs. A key found there was also sent to the model provider.
Files with findings carry a hint on how that client references the environment instead of a literal, for example "env": {"API_KEY": "${API_KEY}"} in Claude Code's .mcp.json or ${input:...} prompts in VS Code.
What it detects
64 regex detectors, plus an entropy check and base64 decoding:
- Entropy: quoted strings of 20+ characters assigned to a variable, with an empirical entropy of at least 4.5 bits/char, when no specific detector claimed the span.
- Base64: runs of 20+ base64 characters (standard or URL-safe) that decode to printable text are decoded once and scanned again, so a credential in a Kubernetes Secret manifest, a Basic auth header or an encoded PEM key is found. The finding is named after the inner detector with
(base64). - Formats come from the gitleaks, betterleaks and trufflehog rule sets.
sb_publishable_keys, which are meant to be public, are not reported.
For credentials in URLs the reported value is the password, and the allowlist judges the password alone: postgres://app:<literal>@${DB_HOST}/app is still reported.
What it deliberately ignores (allowlist)
Each candidate value is checked against these heuristics before being reported:
- Too short: values under 8 characters.
- Masked: values that are mostly (≥ 80%)
X,x,*or dots, including vendor prefixes followed by anXXXX…run. example,placeholder,changemeand your-…-here markers, and<angle brackets>.- Templates:
${VAR},{{ jinja }},{% … %},<%= … %>,#{…}. - Variable references: a value that is only
$UPPER_CASE_VAR,$(command),$env:VARor%VAR%. - Format placeholders:
%(name)sor{name}. - Environment lookups: values referencing
os.environorprocess.env. - Generic assignments and entropy only: code rather than a literal (
os.getenv("X"),settings.DB_PASSWORD,SECRETS[0], one side of a concatenation), values shaped like a regular expression (^(Write|Edit)$,[a-z]{32}), plain links with no credentials, query or fragment, and filesystem paths (C:\Users\...,~/...,/usr/local/...), which fill agent configs. These rules never apply to vendor formats. - Reserved documentation hosts: a credentialed URL pointing at
example.com/.net/.org,*.exampleor*.invalid.
Inline suppression
detect-secrets' pragma: allowlist secret and gitleaks' gitleaks:allow work too, so files annotated for those tools need no changes. Markers are case-insensitive, cover only their own line, and apply to staged and committed lines. Suppressed findings are counted in suppressed, never hidden silently.
Project configuration
mcp-secret-sentinel init writes a commented .secret-sentinel.toml. The same keys work in a [tool.secret-sentinel] table of pyproject.toml. The file is found from the scanned path upwards, stopping at the repository root, and applies to the CLI, the MCP tools and the agent hooks alike.
Unknown keys, unknown detector names and invalid regexes are errors that name the file and the key, so a typo cannot silently weaken a scan. Custom rules run before the built-in detectors and show up in SARIF as their own rules.
Baselines
Adopting a scanner on an existing repository usually means a few known findings (old test fixtures, revoked keys). Review them, then accept them:
Later scans report only secrets that are not in the baseline, and count the rest in baselined. The file stores a salted PBKDF2 fingerprint of each value (never the value, never a fast hash), plus the file and line to help reviewers. Matching ignores the line, so an accepted value stays accepted when the code around it moves; private keys, whose detected header is the same for every key, are tied to their file name as well. The file is written where scans look for it: the config's baseline path, else the project root. Commit it; scan --no-config ignores it.
Command line
mcp-secret-sentinel with no arguments starts the stdio server, so MCP client configs stay one word long. With a command it becomes a CLI:
Exit status: 0 clean (or only findings below --fail-on), 1 findings at or above --fail-on, 2 usage error (bad option, missing path, not a git repository, unknown revision, broken config). Output is redacted in every format.
Block commits with a git hook
This writes .git/hooks/pre-commit (or the directory core.hooksPath points at). The hook runs scan --staged with the Python that installed it, so a commit is refused while its staged lines contain a secret; git commit --no-verify skips it once. The installer never overwrites another tool's hook unless you pass --force, and then keeps the old one as pre-commit.bak.
With the pre-commit framework:
GitHub Action
The action writes a redacted SARIF report to code scanning (one rule per detector, with security-severity), puts the text report in the job summary, and fails the step on findings at or above fail-on. A scan that cannot run (a bad range, a shallow clone, a broken config) fails with its own error instead of being reported as findings. --format sarif on the CLI produces the same SARIF 2.1.0 log for any other CI.
How it works
Encodings and line numbers
Files are decoded by byte-order mark (UTF-8, UTF-16 LE/BE, UTF-32) before the binary check, and BOM-less UTF-16 is recognised too, so the output of Windows PowerShell 5.1's > and Out-File is scanned instead of skipped. Lines are split on \n only, so form feeds, \x85, U+2028 and U+2029 inside a line never shift the reported line numbers.
Redaction guarantee
Every finding shows at most the first 4 characters, and never more than a quarter of the value, plus the total length: "hook…(77 chars)", "Tr…(8 chars)". The full value never appears in the output, the transcript, hook decisions or logs. This is enforced in code (a single redact() choke point) and in the test suite, which asserts that raw values are absent from serialized results, hook decisions and real MCP stdio traffic, structured content included.
Git scans read the text, not your diff settings
The git tools parse git diff / git log -p output, and local settings could change it: an external diff tool replaces the diff, diff.mnemonicPrefix or diff.noprefix corrupt the file names. Every git call therefore passes --no-ext-diff --no-textconv --src-prefix=a/ --dst-prefix=b/ -U0 --inter-hunk-context=0 --no-color, overrides core.quotePath, core.fsmonitor, diff.noprefix, diff.mnemonicPrefix, diff.relative, diff.submodule, log.showSignature and log.showRoot with -c, drops GIT_EXTERNAL_DIFF / GIT_DIFF_OPTS, takes no optional locks, closes stdin, and rejects revisions that start with -. The diff parser is a state machine driven by the hunk line counts, so an added line that reads +++ something is content, never a file header.
Limitations
- Regex detection, not verification: findings are not checked against the provider (that would send your secrets over the network). Dedicated scanners such as gitleaks, betterleaks or trufflehog, with hundreds of rules and optional live verification, belong in your pipeline too; this is the fast local checkpoint an agent runs before the commit exists.
- Outside git, only simple root-
.gitignorepatterns apply (no negations, no**, no nested files). Inside a git work tree the file list comes from git and every rule applies. - Entropy needs diversity: a candidate needs at least 23 distinct characters to clear 4.5 bits/char. Short random strings are covered by the regex detectors instead.
- Unquoted generic assignments are only detected in dotenv-style
UPPER_CASE=valuelines, a deliberate trade against false positives. - Line-by-line matching: a secret split across lines is only caught by its first line (such as a
BEGIN PRIVATE KEYheader). Base64 is decoded one level deep. - Inline suppression is same-line only, because in a zero-context diff the line above is usually not visible.
- Merge commits are not diffed (git's default for
git log -p), so a secret introduced only while resolving a conflict is missed by the range and history scans;scan_git_stagedstill sees it before the merge commit is made. - Binary files in git are not scanned; the summary lists them by name.
- Cursor hook support follows Cursor's published hook protocol; Claude Code's is covered by end-to-end tests over a real pipe.
Development
From the source tree, python -m mcp_secret_sentinel runs the CLI (the MCP server with no arguments). core.py, config.py, agents.py and hooks.py use only the standard library; server.py holds the MCP wiring.
The test suite never contains a realistic secret literal: every positive fixture is assembled at runtime by concatenation, and a test scans this repository and requires it to be clean. It covers every detector, the allowlist, base64 decoding, entropy, redaction, encodings, line numbers, git parsing against real repositories, the CLI as a subprocess, hook decisions (including through the plugin's shell launcher), the agent-config audit, configuration and baselines, and the MCP server over real stdio with the SDK's own client, structured output included. CI runs it on Linux, Windows and macOS, on Python 3.10 to 3.13, and on both majors of the MCP SDK.
Related MCP servers
Part of a family of small, dependency-light MCP servers:
- mcp-decision-lab: weighted decision matrices with sensitivity analysis
- mcp-devils-advocate: stress-test a claim with devil's advocate, premortem and assumption audits
- mcp-git-historian: churn hotspots, blame summaries, bus factor
- mcp-memory-vault: persistent memory with SQLite FTS5 search
License
MIT
来源:README.md,提交 4fc3e29
工具
0版本历史
1- v0.3.0最新Oct 19, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分