Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add JKHeadley/instar --skill credential-leak-detectorgit clone --depth 1 https://github.com/JKHeadley/instarWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/jkheadley/instar/credential-leak-detector)<a href="https://agentmods.dev/skills/jkheadley/instar/credential-leak-detector"><img src="https://agentmods.dev/badge/skills/jkheadley/instar/credential-leak-detector/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/jkheadley/instar/credential-leak-detector"><img src="https://agentmods.dev/badge/skills/jkheadley/instar/credential-leak-detector.svg" alt="Reviewed on agentmods" width="80" height="20"></a>- NVIDIA SkillSpector warn
SkillSpector: 1 finding, up to medium
These are SkillSpector’s own severities. On a checked sample its high-severity flags on skills were ~96% false positives — a documented command, a public API, a “never do X” rule — so we show them as a caution to read, not a verdict. Why →
- medium MCP Rug Pull · line 374 npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.Fix: Pin the version: npx @scope/[email protected]
What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00000 | $0.02995 |
| Opus 5 | $0.00000 | $0.01497 |
| Sonnet 5 | $0.00000 | $0.00599 |
| Haiku 4.5 | $0.00000 | $0.00299 |
Grade A, and why
credential-leak-detector scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 10d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 378 lines — stays where its author put it; the contents beside it link to each section on GitHub.
credential-leak-detector — Catch Leaked Credentials Before They Spread
Every time your agent runs a Bash command, the output flows back into the conversation — and into your API provider's logs, any monitoring tools, and the model's context window. If that output contains an API key, a private key, or a database password, the credential is now exposed in places you never intended.
This hook scans every Bash tool response for 14 credential patterns before the output reaches the agent. Critical matches (API keys, AWS credentials, private keys) get blocked entirely. High-severity matches get redacted with a warning. Suspicious patterns get flagged as advisories. No external dependencies — just Python stdlib.
What Gets Detected
Critical (Blocks the response)
| Pattern | Example Match |
|---|---|
| OpenAI API keys | sk-proj-abc123... |
| Anthropic API keys | sk-ant-api03-... |
| AWS access keys | AKIA1234567890ABCDEF |
| GitHub tokens (classic) | ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
| GitHub fine-grained PATs | github_pat_xxxxxx... |
| Stripe secret keys | sk_live_xxxx...xxxx |
| PEM private keys | -----BEGIN RSA PRIVATE KEY----- |
High (Blocks or redacts with warning)
| Pattern | Action |
|---|---|
| Google API keys | Block |
| Slack tokens | Block |
| SendGrid API keys | Block |
| Twilio auth keys | Redact + warn |
| Bearer auth tokens | Redact + warn |
Medium (Advisory warning)
| Pattern | Note |
|---|---|
Generic password=, secret=, api_key= assignments |
Common in config output |
| 64-character hex strings | Possible SHA-256 hashes or keys |
Installation
Step 1: Create the hook script
mkdir -p .claude/hooks
Create .claude/hooks/credential-leak-detector.py with the contents below.
The Script
Save this as .claude/hooks/credential-leak-detector.py:
#!/usr/bin/env python3
"""
credential-leak-detector.py — PostToolUse hook that scans Bash output
for leaked credentials. Blocks critical leaks, redacts high-severity
matches, warns on suspicious patterns.
Exit code 2 = block (critical credential found)
Exit code 0 = allow (clean or advisory-only)
"""
import sys
import json
import re
# --- Masking ---
def mask(value):
"""Mask a credential: first 4 + **** + last 4, or full mask if short."""
v = value.strip()
if len(v) < 12:
return "*" * len(v)
return v[:4] + "****" + v[-4:]
# --- Pattern Definitions ---
# (name, regex, severity, action)
# severity: critical, high, medium
# action: block, redact, warn
PATTERNS = [
# Critical — Block
("OpenAI API key",
r'(sk-(?:proj-)?[a-zA-Z0-9]{20,})',
"critical", "block"),
("Anthropic API key",
r'(sk-ant-api[a-zA-Z0-9_-]{90,})',
"critical", "block"),
("AWS access key",
r'(AKIA[0-9A-Z]{16})',
"critical", "block"),
("GitHub token (classic)",
r'(gh[pousr]_[A-Za-z0-9_]{36,})',
"critical", "block"),
("GitHub fine-grained PAT",
r'(github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})',
"critical", "block"),
("Stripe secret key",
r'(sk_(?:live|test)_[a-zA-Z0-9]{24,})',
"critical", "block"),
("PEM private key",
r'(-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----)',
"critical", "block"),
# High — Block
("Google API key",
r'(AIza[0-9A-Za-z_-]{35})',
"high", "block"),
("Slack token",
r'(xox[bpors]-[0-9a-zA-Z-]{10,})',
"high", "block"),
("SendGrid API key",
r'(SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43})',
"high", "block"),
# High — Redact
("Twilio auth key",
r'(SK[0-9a-fA-F]{32})',
"high", "redact"),
("Bearer auth token",
r'(?:Authorization|Bearer)\s*[:=]\s*Bearer\s+([^\s]{20,})',
"high", "redact"),
# Medium — Warn
("Generic secret assignment",
r'(?:password|secret|token|api_key)\s*[=:]\s*[\'"]?([^\s\'"]{16,})',
"medium", "warn"),
("High-entropy hex string",
r'\b([a-fA-F0-9]{64})\b',
"medium", "warn"),
]
# --- Main ---
def scan(text):
"""Scan text for credential patterns. Returns list of findings."""
findings = []
for name, pattern, severity, action in PATTERNS:
matches = re.findall(pattern, text)
for m in matches:
findings.append({
"name": name,
"severity": severity,
"action": action,
"matched": m if isinstance(m, str) else m[0],
})
return findings
def main():
try:
payload = json.load(sys.stdin)
except Exception:
sys.exit(0)
tool_name = payload.get("tool_name", "")
tool_response = payload.get("tool_response", "")
# Only scan Bash output
if tool_name != "Bash":
sys.exit(0)
if not tool_response:
sys.exit(0)
# Handle tool_response as string or dict
if isinstance(tool_response, dict):
text = tool_response.get("stdout", "") + tool_response.get("stderr", "")
else:
text = str(tool_response)
if not text:
sys.exit(0)
findings = scan(text)
if not findings:
sys.exit(0)
# Classify findings
blockers = [f for f in findings if f["action"] == "block"]
redacts = [f for f in findings if f["action"] == "redact"]
warnings = [f for f in findings if f["action"] == "warn"]
# Critical/high blockers — stop the response
if blockers:
details = []
for f in blockers:
details.append(
f" - {f['name']} [{f['severity']}]: {mask(f['matched'])}"
)
reason = (
"[credential-leak-detector] Credential(s) detected in command output. "
"Response blocked to prevent exposure.\n\n"
"Detected:\n" + "\n".join(details) + "\n\n"
"The command output contained live credentials. Do NOT re-run this "
"command or attempt to extract these values. If you need to verify "
"a credential exists, check the env var or file without printing "
"its value."
)
print(json.dumps({"decision": "block", "reason": reason}))
sys.exit(2)
# Redact findings — allow but warn with masked values
messages = []
if redacts:
parts = []
for f in redacts:
parts.append(f" - {f['name']}: {mask(f['matched'])}")
messages.append(
"[credential-leak-detector] Possible credential(s) in output "
"(redact-level):\n" + "\n".join(parts) + "\n"
"Avoid storing, logging, or repeating these values."
)
# Warn findings — advisory only
if warnings:
parts = []
for f in warnings:
parts.append(f" - {f['name']}: {mask(f['matched'])}")
messages.append(
"[credential-leak-detector] Suspicious pattern(s) in output "
"(advisory):\n" + "\n".join(parts) + "\n"
"These may be secrets. Avoid including them in commits, logs, "
"or messages."
)
if messages:
print(json.dumps({"additionalContext": "\n".join(messages)}))
sys.exit(0)
if __name__ == "__main__":
main()
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 10d ago First seen · 378 lines · 0 tokens per session scan A 3b0b77200bd8
credential-leak-detector is a skill published in the GitHub repository JKHeadley/instar (79 stars, last pushed yesterday), licensed MIT. It costs nothing until one of its globs matches a file; then it loads 2,995 tokens. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
javascript-sast
JavaScript and Node.js security scanning. Checks dependency vulnerabilities via npm audit and source patterns for XSS, eval, and prototype pollution.
jest-patterns
Jest and Vitest testing patterns including describe/it blocks, expect matchers, mocking, and async test strategies for JavaScript and TypeScript.
code-review
Use when reviewing a code change or diff for correctness, security, missing tests, and convention violations before opening or approving a PR. Review independently and adversarially, then fix high-confidence issues.
tech-spec
Use when a task is under-specified and needs a written technical specification BEFORE any code is written or changed. This skill only researches and documents — it never edits source files. Do not invoke for implementing, reviewing, or simplifying existing code.
simplify
Use after writing or modifying code to improve its clarity, reuse, simplicity, and efficiency without changing behavior. Not for finding correctness bugs — that is code review.
caveman
Use to minimize token use on long or repetitive agent work. Cut all prose to the bone — no preamble, no restating the task, no narrating steps, no closing summary. Spend tokens on the work, not on words.