Secret scanning often starts at Git. AI coding agents can make that too late.
They can read local files, summarize logs, run commands, and transform sensitive context before anything is committed. shk is a local-first CLI for that messy pre-commit space: scan secrets and PII, mask prompts, and install managed hooks for Claude Code, Cursor, Codex, GitHub Copilot, Antigravity, and Windsurf.
Kazuki-tam
/
security-harness-kit
A Rust CLI that scans for secrets, PII, and sensitive data — with native hooks for AI coding assistants to prevent leaking credentials into AI context.
security-harness-kit (shk)
shk is a local-first guardrail for AI-assisted development. It helps keep secrets, PII, and risky project surfaces out of AI tool context, Git commits, generated output, and everyday local workflows. It can also encrypt .env files and inject decrypted values only when running local commands.
shk scan .
Example output:
3 findings
HIGH secret.openai_api_key src/app.ts:12 Possible OpenAI API key detected
MED pii.ja.phone config/dev.ts:5 Japanese phone number detected
MED pii.en.ssn docs/test.md:8 US Social Security Number detected
Why
AI coding agents can read project files, run commands, and transform sensitive input into new files. shk adds local checks around those workflows so teams can audit, mask, or block risky content before it leaves the intended boundary.
With shk, you can:
- Scan project paths and Git-staged files for common secrets and PII across source code, Markdown, plain text, Office documents (
.docx,.xlsx,.pptx), and…
The problem is no longer just "secret reaches Git"
Most secret-scanning workflows are built around a familiar boundary: stop credentials before they land in Git, CI logs, or a release artifact.
AI coding agents move that boundary earlier.
An agent might read a file while following an import chain. It might summarize a pasted error log. It might run a shell command that prints .env contents. It might create a new file that quietly contains a token from earlier context. None of that requires a commit.
That is the gap shk is trying to cover: the local, messy, pre-commit space where AI tools actually operate.
What shk does in practice
shk is not one more dashboard you have to check. It is a single Rust binary that you put around the workflows where sensitive context tends to leak:
-
Before sharing context with an AI tool, use
shk maskto redact secrets and PII from a prompt, log, snippet, or even an Office document. - Before an AI tool reads, writes, fetches, or runs something, use managed hooks to audit or block risky operations.
-
Before trusting an MCP setup, use
shk mcp auditto statically check MCP client configs for unsafe package, credential, HTTP, and filesystem settings. - Before a commit or pull request, use the same scanner through Git pre-commit hooks and GitHub Actions.
That gives you one policy file, one set of rules, and one exit-code contract across local use, AI hooks, Git, and CI.
A quick tour
Node.js users can install via npm (the installed command is still shk):
npm install -g security-harness-kit
macOS and Linux users can install the latest release with the bundled installer:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Kazuki-tam/security-harness-kit/releases/latest/download/shk-cli-installer.sh | sh
Or via Homebrew:
brew install Kazuki-tam/homebrew-tap/shk
Windows users can install from PowerShell:
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/Kazuki-tam/security-harness-kit/releases/latest/download/shk-cli-installer.ps1 | iex"
Start with a policy file:
shk init
When package.json is present, shk init can also apply package-manager supply-chain hardening such as ignore-scripts=true and minimum-release-age gates for npm, pnpm, Yarn, and Bun.
Scan the current project:
shk scan .
Example output:
3 findings
HIGH secret.openai_api_key src/app.ts:12 Possible OpenAI API key detected
MED pii.ja.phone config/dev.ts:5 Japanese phone number detected
MED pii.en.ssn docs/test.md:8 US Social Security Number detected
Scanning is not limited to source code. Text is also extracted from .docx, .xlsx, .pptx, and text-layer .pdf files, so a stray credential in a shared spec document is treated the same as one in code.
Need a machine-readable report for automation? Use JSON or SARIF. Raw matched values are not emitted; findings use redacted_value: "[REDACTED]".
shk scan . --json
shk scan . --sarif
Need to paste a production log into an AI chat? Mask it first:
shk mask < prompt.txt
shk mask report.docx --output report.redacted.docx
Copy-paste is its own leak channel, so the clipboard gets the same treatment:
shk clipboard scan
shk clipboard mask --write
Need to protect the commit path?
shk scan --staged
shk hooks install
And because "we committed it last year" is still a leak, shk can scan Git history itself:
shk scan --git-history --preview
shk scan --git-history --ref HEAD~50..HEAD
The basic loop is intentionally boring: scan, review, mask, and block only when a configured threshold is met.
The AI-specific part: managed hooks
The more interesting piece is shk hooks install-ai.
Instead of relying on you to remember to scan every prompt, shk can write managed hook entries into supported AI tool configs:
# Preview the changes first.
shk hooks install-ai --dry-run
# Start in audit mode: log findings, never block.
shk hooks install-ai --audit
# Or target one tool.
shk hooks install-ai --tool cursor
shk hooks install-ai --tool claude-code --global
Project-level installs are the default. Global installs write to the user-level config for the selected tool.
Supported integrations:
| Tool | Managed config |
|---|---|
| Claude Code | .claude/settings.json |
| Cursor | .cursor/hooks.json |
| Codex | .codex/config.toml |
| GitHub Copilot | .github/hooks/shk-security.json |
| Antigravity | .agents/hooks.json |
| Windsurf (Cascade) | .windsurf/hooks.json |
Each integration speaks the tool's native hook contract — stdout JSON decisions for Copilot and Antigravity, exit codes plus stderr for Windsurf, and so on — so you do not have to learn six different hook schemas yourself.
The managed entries are easy to identify later: most configs tag them with "_shk_managed": true or # shk-managed-start / # shk-managed-end markers, while Copilot and Windsurf keep a schema-clean config and identify managed entries by their command string. Re-running replaces managed entries and leaves your own entries in place.
There are also optional hardening flags where the tool supports them: --apply-deny merges recommended permission deny entries for sensitive files and dangerous actions (Claude Code), and --apply-sandbox applies supported sandbox settings (Claude Code and Codex).
It checks intent, not only text
Secret scanners usually inspect content. AI hooks also need to inspect actions.
In hook mode, shk reads the AI tool's JSON hook payload and runs an action guard before scanning extracted text. The guard looks for operation shapes such as:
- Reads or writes involving sensitive paths.
- Commands that dump
.env-style files. - Destructive recursive removal.
- Direct database mutation commands.
- Privilege or system configuration changes.
- External transfer commands.
- Package-manager operations.
The default recommended profile is conservative. A strict profile can also block opaque execution forms such as bash -c, python -c, and node -e, because pretending to safely interpret every nested command string is usually worse than being explicit about the risk.
You can tune this in shk.toml with [action_guard] allow and deny patterns.
Audit first, then block
Hooks make decisions through exit codes, so the contract is small:
| Code | Meaning |
|---|---|
0 |
No finding at or above the active threshold, or audit/post-hook completed. |
1 |
Scan or MCP audit findings met or exceeded the active threshold. |
2 |
A blocking AI pre-hook fired, or a scan/MCP audit runtime or configuration error occurred. |
--audit always exits 0. Post-tool hooks also always exit 0, because the operation already happened and the useful behavior is reporting, not pretending to undo it.
That makes rollout straightforward:
shk hooks install-ai --audit
Let it run for a few days, then review the log with the built-in summarizer:
shk audit
shk audit --since 7d --tool cursor
The log is metadata-only: counts, tool name, hook phase, display path, suppressed count, and maximum severity. It does not store raw matched values, prompt bodies, or command text.
Once the noise level is acceptable, reinstall in blocking mode. If you still want visibility into what gets blocked, --log-blocked keeps blocking while appending metadata-only block entries to the same audit log:
shk hooks install-ai --log-blocked
Auditing the MCP layer
Hooks cover what an agent does. MCP configuration decides what an agent can reach, and it deserves its own check.
shk mcp audit statically audits MCP client configuration files — the JSON/TOML configs used by Claude Code, Cursor, Codex, VS Code / Copilot, and friends — for risky patterns: unpinned npx / uvx / pipx packages and auto-install flags, shell wrappers, filesystem servers exposed at / or the home directory, non-loopback http:// endpoints, and secrets in URLs. Configured values also pass through the same secret rule engine as shk scan.
shk mcp audit
shk mcp audit --global
shk mcp audit --json
shk mcp audit --sarif
It is deliberately a static audit, not a runtime proxy or gateway. It reads config files and reports; it does not sit between your agent and its MCP servers.
Same binary for Git and CI
AI hooks are the new boundary, but Git still matters.
Install a managed pre-commit hook:
shk hooks install
Generate a GitHub Actions workflow:
shk ci init github
# Add GitHub code scanning alerts and PR annotations:
shk ci init github --upload-sarif
The generated workflow installs the prebuilt release binary (no Rust toolchain rebuild in CI), uses a minimal GITHUB_TOKEN scope, cancels stale PR runs, and fails on high-severity findings. With --upload-sarif, findings also show up as GitHub code scanning alerts and PR annotations.
If you prefer not to generate a workflow at all, there is a composite action:
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: Kazuki-tam/security-harness-kit@v1
with:
path: .
fail-on: high
upload-sarif: true
You can also generate rollout variants when you need them:
-
shk ci init github --mode auditfor non-blocking CI adoption. -
shk ci init github --shk-version v0.6.1for reproducible pinned installs.
For PR-focused scans, shk scan --changed-since origin/main scans only files changed relative to the merge base.
Encrypted .env files that decrypt only at runtime
Plaintext .env files are exactly the kind of thing an AI agent stumbles into. shk env closes that loop:
shk env encrypt .env --in-place
shk env run -- npm test
encrypt rewrites the .env with encrypted values using shk's native encryption, following the familiar dotenv conventions (DOTENV_PUBLIC_KEY* in the file, KEY="encrypted:..." values). The private key goes into the OS keyring instead of a file on disk. run decrypts in memory and injects values only into the child process, so nothing sensitive sits in your shell environment or in a plaintext file for an agent to read. Existing dotenvx users can import their keys once (shk env dotenvx import-keys .env.keys) and keep their encrypted files working without the external dotenvx binary.
Teams can opt in to a 1Password backend for the private keys — shared vault distribution, centralized revocation, and Business audit logs — and migrate existing keys with shk env key migrate --to 1password.
A few workflows beyond scanning
These are the commands that make shk feel less like a one-off scanner and more like a local security harness:
-
shk doctorchecks project hygiene, including ignore coverage and plaintext.envfiles. -
shk doctor ignore --fixappends missing required patterns to.gitignore. -
shk doctor workflows --fixhardensactions/checkoutsteps that keep credentials persisted. -
shk secrets pushpushes dotenv payloads into AWS Secrets Manager or GCP Secret Manager through the officialaws/gcloudCLIs, with dry-run, audit logging, and PII pre-scan. -
shk skills installdeploys an embedded agent skill for Claude Code, Codex, Cursor, Copilot, Antigravity, and Windsurf so agents know how to callshkin the project.
All of these are optional. The tool is still useful if you only use scan, mask, and hooks.
A desktop app, for the same local boundary
Not everyone on a team lives in a terminal. shk Desktop is a local GUI over the same engine: project scanning, AI-oriented masking, setup automation, and audit review.
While it is open, it also raises an OS notification whenever a hook blocks AI activity in any of your projects — so a silent exit code 2 in some agent's log becomes something a human actually notices.
Installers are published from GitHub Releases; macOS builds are Developer ID signed and notarized.
What it intentionally does not promise
Security tooling gets dangerous when it overstates its guarantees, so here is the honest scope.
shk is pattern-based. Built-in rules combine hand-tuned shk detections with generated secret.gitleaks.* rules adapted from the gitleaks default configuration. That covers many common providers and formats, but false positives and false negatives are both possible.
The PII rules are designed for "do not paste this into an AI prompt" hygiene. They are not compliance evidence.
The action guard is heuristic. It can flag risky operation shapes in hook payloads, but it is not a shell interpreter and should not pretend to be one.
The MCP audit is static. It reviews configuration files; it does not intercept or sandbox live MCP traffic.
shk is also not a replacement for a secret manager, a cloud provider's scanning features, or a dedicated enterprise secret-scanning platform. It is a local guardrail layer for the part of development where AI tools read, transform, and generate context.
Try it on an existing repo
The smallest useful sequence is:
shk init
shk scan .
shk hooks install-ai --audit
If the audit log looks reasonable after a short soak period, reinstall without --audit (or with --log-blocked for visibility) and block on high-severity pre-hook findings. If it is noisy, tune [thresholds], [[allowlist]], and [action_guard] first.
The goal is not to make the tool dramatic. The goal is to make secrets, PII, and risky AI operations visible before they leave the local development boundary.
- Repo: github.com/Kazuki-tam/security-harness-kit
- Docs: Installation, Commands, Configuration, Detection Model, and GitHub Actions integration are linked from the README.
- License: MIT.
Issues, rule contributions, and false-positive reports are welcome. The rule set gets better as more real codebases run through it.

Top comments (0)