Check skills, plugins and MCP servers before they run with your agent's permissions — and stop secret leaks, destructive commands and prompt injection while you work.
  • JavaScript 79.4%
  • HTML 20.2%
  • Python 0.3%
  • Shell 0.1%
Find a file
Kjell Tore Guttormsen 58d2e8ad8d
fix(av-surface): no runnable base64-to-shell line on disk
PLAN § v8.1.3 tillegg a. The bash-evasion gallery's T8 comment held a
complete base64-decode-into-shell line whose 16-char blob decodes to a
home-directory deletion, under probe (b)'s 24-char floor. Probe (b2)
found two more of the same shape, fixed here too: the gallery README's
T8 row and tests/e2e/attack-chain.test.mjs (an /etc deletion). Chosen
over an exception list because the gate should have none.

The gallery and the e2e test now encode the blob at runtime from the
same fragments; the README shows a placeholder. Gallery: 10/10 blocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 11:35:50 +02:00
.claude-plugin chore(release): v8.1.2 — node_modules and plugin dir foreign, posture credit honest 2026-09-22 21:40:05 +02:00
agents refactor(agents): skill-scanner detection rules move to knowledge 2026-09-22 14:11:15 +02:00
bin chore(llm-security): v7.8.3 — docs consistency + version bump (#8,#44,#45,#46,#47) 2026-07-18 10:50:50 +02:00
ci feat(ci): add CI/CD integration — --fail-on, --compact, pipeline templates 2026-04-10 14:59:05 +02:00
commands docs(scan): command description names the URLs git-clone accepts 2026-09-22 21:05:47 +02:00
docs fix(llm-security): SIG self-flagged the vendored commons it detects from 2026-08-13 21:41:09 +02:00
examples fix(av-surface): no runnable base64-to-shell line on disk 2026-09-23 11:35:50 +02:00
hooks refactor(hooks): split two rule names so no download-into-shell literal sits on disk 2026-09-22 14:30:32 +02:00
knowledge refactor(agents): skill-scanner detection rules move to knowledge 2026-09-22 14:11:15 +02:00
playground chore(llm-security): v7.7.2 — language consistency pass 2026-05-19 06:47:44 +02:00
reports chore(privacy): scrub real-org references from plugin internals (phase 2) 2026-05-03 04:28:15 +02:00
scanners fix(watch): run the orchestrator with the watched project as cwd 2026-09-23 11:34:55 +02:00
scripts refactor(llm-security): build the SIG ruleset from vendored commons (malware-signatures 0.1.0) 2026-08-13 21:28:14 +02:00
templates fix(llm-security): template — v1 → v2 risk constants + narrative_audit block 2026-04-29 12:45:28 +02:00
test-fixtures/trifecta-plugin feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
tests fix(av-surface): no runnable base64-to-shell line on disk 2026-09-23 11:35:50 +02:00
.editorconfig feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
.gitignore test(llm-security): add red AV-surface probe for the v8.1.0 Defender plan 2026-09-22 12:39:26 +02:00
.llm-security-ignore docs(ignore): drop the drifting suppressed/no-ignore counts from the header 2026-09-22 21:06:22 +02:00
.npmignore feat(ci): add CI/CD integration — --fail-on, --compact, pipeline templates 2026-04-10 14:59:05 +02:00
CHANGELOG.md chore(release): v8.1.2 — node_modules and plugin dir foreign, posture credit honest 2026-09-22 21:40:05 +02:00
CLAUDE.md docs(readme): shorter, concrete value proposition, antivirus alerts for organizations 2026-09-23 09:42:41 +02:00
CONTRIBUTING.md fix(llm-security): correct distribution URLs to marketplace path 2026-05-01 06:20:54 +02:00
LICENSE feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
llms.txt docs(llm-security): add llms.txt as the in-repo agent entry point 2026-08-21 11:29:51 +02:00
package.json chore(release): v8.1.2 — node_modules and plugin dir foreign, posture credit honest 2026-09-22 21:40:05 +02:00
README.md docs(readme): lead with the value proposition, matching the new forge description 2026-09-23 10:11:48 +02:00
SECURITY.md docs(readme): shorter, concrete value proposition, antivirus alerts for organizations 2026-09-23 09:42:41 +02:00
V3-ANNOUNCEMENT.md docs(llm-security): repo-standard gate to 0 ERROR 2026-08-03 22:02:29 +02:00
V3-UPGRADE.md docs(llm-security): D12 disclosure + last dead pre-split reference 2026-08-09 10:04:33 +02:00

LLM Security Plugin for Claude Code

Check skills, plugins and MCP servers before they run with your agent's permissions — and stop secret leaks, destructive commands and prompt injection while you work.

Solo-maintained, fork-and-own. A starting point, not a vendor product. Issues are welcome as signals; pull requests are not accepted. See GOVERNANCE.md.

AI-generated: all code produced by Claude Code through dialog-driven development. Every change is human-directed, reviewed, and validated before commit. Per Anthropic Consumer Terms §4, ownership of outputs is assigned to the user; this plugin is licensed MIT.

Version Platform Scanners License

Warning

Rolling this out in an organization? Antivirus and EDR products such as Microsoft Defender can raise alerts on files in this repository, because it contains detection rules and descriptions of attack techniques. Read Antivirus and EDR alerts before you deploy, and report any alert to security@fromaitochitta.com so it can be fixed.

Why

A Claude Code extension does not just run code — it can give your agent instructions. A malicious skill can tell Claude to read ~/.ssh, post your environment variables to a webhook, or rewrite its own configuration, while presenting itself as a harmless "project health dashboard". This is the npm/PyPI supply-chain problem with LLM agency added.

What you get:

  • Guardrails from the moment you install. Nine hooks run on every prompt and tool call. Five block: secrets written to files, writes to .env/.ssh/credentials, destructive shell commands, compromised or typosquatted packages, and prompt injection. Four warn.
  • A verdict before you install anything. /security scan <url> --deep clones a repository into a temp directory (OS-sandboxed on macOS and on Linux with bwrap), runs 14 deterministic scanners plus LLM analysis, and returns ALLOW / WARNING / BLOCK — without loading the repository into your session.
  • A grade for your own setup. /security posture scores your Claude Code configuration across 16 posture categories in seconds; /security audit gives an A–F report with the fixes.

Findings map to OWASP LLM Top 10 (2025), OWASP Agentic AI Top 10, OWASP Skills Top 10, MCP Top 10 and the AI Agent Traps taxonomy (Google DeepMind).

Install

Requires Claude Code v2.x+ and Node.js (any recent LTS).

claude plugin marketplace add https://git.fromaitochitta.com/open/ktg-plugin-marketplace.git
claude plugin install llm-security@ktg-plugin-marketplace

The hooks are active immediately. No configuration is needed.

First five minutes

Run You get
/security posture Scorecard for this project's Claude Code setup, with the top gaps
/security scan <path|url> --deep ALLOW / WARNING / BLOCK for a skill, plugin, MCP server or repository
/security plugin-audit <path|url> Install / Review / Do Not Install for a plugin
/security audit Full A–F audit with a prioritized action plan
/security harden --apply Grade A reference config (settings.json, CLAUDE.md, .gitignore), with backup

Important

Scan a repository before you clone it. A poisoned CLAUDE.md enters the model's context the moment you open a cloned repository — before any hook can run. /security scan <url> --deep inspects it from a pre-extracted evidence package instead.

What runs automatically

Hook When Effect
Prompt injection scan Every prompt Blocks override instructions, spoofed system headers, identity redefinition; decodes obfuscation (Unicode Tag, hex, URL, base64, rot13) first
Secret detection Edit, Write Blocks AWS/Azure/GitHub/npm tokens, PEM keys, database URLs, JWTs, webhook URLs — 19 patterns, extendable in policy
Path guard Edit, Write Blocks writes to .env*, .ssh/, .aws/, .gnupg/, credentials, hook scripts, settings.json
Destructive commands Bash Blocks rm -rf /, pipe-to-shell, fork bombs, chmod 777, eval tricks — after undoing shell obfuscation
Supply chain Bash Blocks known-compromised packages (incl. known typosquats), critical CVEs, and brand-new packages (<72 h, few releases); warns on look-alike names — npm, pip, brew, docker, go, cargo, gem
Output check After every tool Warns on injection in tool output and on MCP tool descriptions that drift over time
Session guard After every tool Warns on the "lethal trifecta": untrusted input + sensitive read + an exfiltration step
Pre-compact scan Before compaction Warns on injection or credentials about to survive into the compacted context
Update check Once a day Tells you when a newer version exists (LLM_SECURITY_UPDATE_CHECK=off disables it)

Injection and trifecta modes (block/warn/off) are set per project in .llm-security/policy.json; the pre-compact mode via LLM_SECURITY_PRECOMPACT_MODE.

All commands

Command Purpose
/security List the sub-commands
/security scan [path|url] Supply-chain gate; --deep adds the 14 deterministic scanners
/security deep-scan [path] The 14 deterministic scanners only, with a synthesized report
/security plugin-audit [path|url] Plugin trust assessment
/security mcp-audit [--live] Audit installed MCP server configs
/security mcp-inspect Connect to running MCP servers and scan their live tool descriptions
/security mcp-baseline-reset Reset the MCP drift baseline after a legitimate server upgrade
/security ide-scan [target|url] Scan VS Code (and forks) and JetBrains extensions, installed or by URL
/security supply-check [path] Re-audit installed dependencies against blocklists, OSV.dev and typosquats
/security posture Quick scorecard, 16 categories
/security audit Full audit, A–F
/security dashboard Posture across every project on the machine
/security diff [path] New / resolved / unchanged findings against a baseline
/security watch [path] Run diff on an interval
/security registry Skill fingerprint registry
/security clean [path] Fix what is safe to fix, ask about the rest (--dry-run to preview)
/security harden [path] Generate a Grade A config
/security threat-model Guided STRIDE × MAESTRO session, 15–30 min
/security red-team 72 attack scenarios against the hooks
/security pre-deploy Pre-deployment checklist

Every report command also writes a self-contained HTML version and prints a link to it. Scanner-by-scanner detail: docs/scanner-reference.md.

For teams and CI

  • Policy as code — .llm-security/policy.json travels with the repository: hook modes, thresholds, audit log path. A scanned foreign repository's own policy and ignore file are not applied, so it cannot suppress its findings. Known exceptions — a tarball or git archive export under your working directory, a Python venv, a vendor/ folder — are listed under 8.1.2 in the changelog.
  • Runs without Claude Code — node bin/llm-security.mjs scan <target> (also deep-scan, posture, ide-scan, audit-bom, benchmark); no API key needed. It is not air-gapped: OSV.dev lookups (package names and versions), npm audit/pip-audit, and DNS checks on URLs it finds reach the network, with no switch to turn them off. Block egress at the network layer if you need an offline run.
  • CI gates — --fail-on <severity> exit codes, --compact output, SARIF 2.1.0. Templates for GitHub Actions, Azure DevOps and GitLab CI in ci/; guide in docs/ci-cd-guide.md.
  • Evidence — JSONL audit trail with OWASP tags for your SIEM, CycloneDX 1.6 AI bill of materials, and posture checks mapped to EU AI Act, NIST AI RMF and ISO 42001.

Antivirus and EDR alerts

This is a security tool. It ships regular expressions for known-bad code, knowledge files that explain how injection, exfiltration and persistence attacks work, and an encoded demo of a malicious plugin. Nothing in it is malware, but products that use machine learning and heuristics — Microsoft Defender among them (next-generation protection) — can still flag such text. A plain SKILL.md in another security repository has been quarantined as Trojan:Script/Wacatac.H!ml.

What still sits on disk as readable text, and is therefore the likeliest to be flagged: the regex signature tables in scanners/commons/ (some name hacking tools as plain words), the attack descriptions in knowledge/, and the injection phrases and sample commands the examples feed to the hooks.

What v8.0 → v8.1.2 did about it

All antivirus work landed in v8.1.0; v8.1.1 and v8.1.2 did not touch it. (v8.0.0 moved the detection tables, including the malware signatures, into the vendored scanners/commons/ data that ships with the plugin.)

Change (v8.1.0) Effect
Test payloads are built at test time in a temp directory, from split strings or rot13 No runnable malicious fixture is stored in the repository
The malicious-plugin demo and the poisoned CLAUDE.md example ship as encoded archives They exist in decoded form only in a temp directory while you run them
Skill-scanner detection lists moved from an agent file to knowledge/; runnable one-liners in knowledge/*.md rewritten as descriptions A quarantined knowledge file does not break the plugin; a quarantined agent file would
Download-into-shell literals removed from hook source The hook that blocks these commands no longer contains one
Gate: tests/av-surface.test.mjs The suite fails if a runnable payload file, a base64 shell-command blob, hidden Unicode (outside the commons conformance corpus), a known payload tree, or a payload literal in agents/commands/hooks returns to disk

Detection is unchanged: the signature tables and the golden baseline are identical before and after.

Not measured: no clone or install has been tested against Defender on a Windows machine. "No alerts" is the design goal, not a verified result.

If you get an alert

  1. Do not exclude the folder. Microsoft advises against exclusions as a fix: "Every exclusion is a protection gap" (exclusions overview).
  2. Report it to Microsoft as a false positive.
    • Managed devices (Defender for Endpoint / Defender XDR): your security team submits the file in the Defender portal under Submissions → Files, classified as Clean (false positive) (how).
    • Single machine: restore it under Windows Security → Protection history (how) and submit it at https://www.microsoft.com/wdsi/filesubmission.
  3. Email security@fromaitochitta.com with the file path, the detection name, the plugin version (or commit), and the antivirus product and its signature version. The alert is handled as a bug: the goal is a patch release in which the file no longer trips the product, with the gate above extended so it stays that way. There is no SLA (see SECURITY.md).

If you only need the scanners and hooks, a sparse checkout keeps knowledge files, tests, examples and docs off disk:

git clone --filter=blob:none --no-checkout https://git.fromaitochitta.com/open/llm-security.git
cd llm-security
git sparse-checkout set scanners hooks
git checkout main

The hooks do not need knowledge; add it to the set line for the typosquat checks, ide-scan, the skill registry and red-team. This affects your own clone only — not what claude plugin install puts in the plugin cache.

Known limitations

Prompt injection cannot be fully prevented with today's model architectures; motivated adaptive attackers defeat every published defense. This plugin raises the cost of an attack with independent layers — it does not guarantee against one.

Limit What to do
A cloned repository's CLAUDE.md loads before any hook runs Scan remotely first: /security scan <url> --deep
Regex cannot catch every novel phrasing of an injection Add an ML classifier such as parry-guard; they run side by side
Remote-scan clones run without an OS sandbox on Windows, and on Linux where bwrap is missing or blocked (Ubuntu 24.04+ by default) — only a warning is printed Git hardening still applies; on Windows run Claude Code in WSL2 or Docker, on Ubuntu allow bwrap in AppArmor
RAG pipelines, LLM gateways, SSO/SCIM are outside a plugin's reach Use platform or infrastructure tooling
Opus with extended context: subagents do not support it and fail Run /model Opus before the security commands

Design rationale: docs/defense-philosophy.md. Hardening guide: docs/security-hardening-guide.md.

Project scope

A solo open-source project in stabilization mode since 2026-05-01: bug and security fixes, Claude Code compatibility, knowledge-base refresh.

Non-goals

Out of scope — fork and own them under MIT if you need them: web dashboards or fleet servers, an inline prompt firewall, real-time IDE scanning, compliance evidence packs, ticketing/chat connectors, hosted ML detectors, SSO/RBAC. See CONTRIBUTING.md for the fork-and-own guide.

Verify it yourself

No CI runs the tests for you — this forge has no Actions runner. From a clean clone:

npm test                                          # the full suite
node scanners/scan-orchestrator.mjs .             # the plugin scanning itself

The self-scan is not clean on purpose: a tool that documents attacks and tests against hostile code trips its own scanners. .llm-security-ignore suppresses the expected findings and explains each one; delete it to see everything.

The encoded malicious-plugin demo is a realistic attack. LLM agents and deterministic scanners together find 85 issues and return BLOCK 100/100 (see its assessment). The commands below run the deterministic half:

DEMO="$(node examples/malicious-skill-demo/materialize.mjs)"   # decodes into a temp dir, prints the path
node scanners/scan-orchestrator.mjs "$DEMO"
rm -rf "$(dirname "$DEMO")"

For the full pipeline, run /security scan <printed path> --deep in Claude Code before removing the directory.

More runnable demonstrations — injection showcase, trifecta walkthrough, MCP rug pull, supply-chain attack, bash evasion — are in examples/.

Upgrading from v7

v8.0.0 removed four environment variables. A removed variable is silently ignored — LLM_SECURITY_INJECTION_MODE=off no longer turns anything off. Find them before you upgrade:

env | grep '^LLM_SECURITY_\(INJECTION_MODE\|TRIFECTA_MODE\|ESCALATION_WINDOW\|AUDIT_LOG\|DEPRECATION_QUIET\)='
grep -rn 'LLM_SECURITY_\(INJECTION_MODE\|TRIFECTA_MODE\|ESCALATION_WINDOW\|AUDIT_LOG\)' \
  ~/.zshenv ~/.bashrc .envrc .github/workflows/ 2>/dev/null

Move each one into .llm-security/policy.json:

Removed env var Policy key Default
LLM_SECURITY_INJECTION_MODE injection.mode block
LLM_SECURITY_TRIFECTA_MODE trifecta.mode warn
LLM_SECURITY_ESCALATION_WINDOW trifecta.escalation_window 5
LLM_SECURITY_AUDIT_LOG audit.log_path unset (off)

LLM_SECURITY_DEPRECATION_QUIET is gone with the warning it silenced. Details in CHANGELOG.md under 8.0.0.

Changelog

  • 8.1.2 (2026-09-22) — Installed packages (node_modules) and Claude Code's plugin directory count as foreign, so their ignore and policy files are not applied.
  • 8.1.1 (2026-09-22) — A clone, submodule or worktree under your working directory counts as foreign.
  • 8.1.0 (2026-09-22) — Antivirus surface (see above); a scanned foreign repository's own ignore and policy files are no longer applied.
  • 8.0.0 (2026-09-18) — Breaking cleanup (see Upgrading from v7); detection tables built from shared, versioned data.

Full history: CHANGELOG.md.

License and contact

MIT — see LICENSE. Built on published research from OWASP, ToxicSkills, ClawHavoc, MCPTox, Pillar Security, Invariant Labs, GHSL Security Lab, Operant AI and Google DeepMind; sources are cited in knowledge/.