Cisco MCP Scanner Plugin

Draft · awaiting review

Claude Code plugin that scans MCP servers and tools for prompt injection, tool poisoning and other risks via the Cisco MCP scanner.

“Useful as a key-free first pass over an MCP server's tools: it flagged all three baited tools without a false alarm, but it reads tools only and reaches for GitHub at start-up.” Would we use it again: with limits.

For Agent supply-chain scanWorks with Claude CodeMaintained cisco-ai-defense, last push 2026-10-16

PluginA plugin bundles skills, commands, hooks or MCP servers for one AI client. by cisco-ai-defense · read from the code at 5d147dc (v4.8.6) on 2026-11-07The date we last read the tool’s files. The code after “at” names the exact version (the git commit) we read; a newer version may differ. · Ran once on 2026-11-07 and did more than it said.Whether we have run the tool in our lab. “Did more than it said” means the run used rights its description does not name; “did no more than it said” means it stayed within them.

Code showsWhat a reading of the code found the tool can do, at the checked version, in the words of the rights table in the record. It is a ceiling, not what the tool did. A right marked unknown has no evidence either way, and that never counts as harmless.

What the code shows, worst first. No run advice yet: the one word needs a read under the full rule.

  1. Level 3. Secrets. The command reads the MCP client configuration files of Windsurf, Cursor and Claude Desktop, which can hold server API keys and tokens.

    scan-known-configs.md L11-18

  2. Level 2. Network. The known-configs scan connects to every remote MCP server listed in local client configs, hosts the user does not name.

    SKILL.md L58-59

  3. Level 2. Execution. The skill tells the agent to launch any program as a stdio MCP server.

    SKILL.md L87-89

  4. Level 2. Persistence. The documented prerequisite installs the scanner package into the active Python environment.

    README.md L16-18

  5. No evidence. Approval. Unknown: the skill and command frontmatter set no allowed-tools, permission mode or auto-approve, so the approval posture cannot be read statically. That never counts as zero.

Before first useSettings for your AI client that limit the tool to the rights its task needs; derived from the code unless marked tested. derived from the code, not tested

  1. Claude Code: run the yara analyzer only (no API keys, no cloud upload); avoid --scan-known-configs and the stdio launch mode unless you trust every server in your local configs; remove scanner and LLM API keys from the environment before a known-configs scan, because every started server inherits it.
Plugin · code showsreach 3 · privileged
12232?FilesNetworkExecutionSecretsPersistenceApproval

What the code can reach, 0 to 3 per right; a dashed point means no evidence, never zero. The three readings

Is it for you?

Made for
  • Scan MCP servers and tools for security threats and risks from inside Claude Code.
  • Detect prompt injection, tool poisoning and other threats in MCP tools, prompts and resources.
  • Detect malicious MCP tools by combining the Cisco AI Defense inspect API, YARA rules and LLM-based analysis.
Use it when
Not for

Nothing excluded by the author in the files read

You need
  • Claude Code, which loads the plugin from its folder with --plugin-dir
  • The cisco-ai-mcp-scanner Python package, installed separately from the plugin
  • Python 3.11.4 or newer

+4 more

Details: You need

Install

linked, not distributed: the Field Guide does not bundle agents or MCP servers

Upstream

pip install cisco-ai-mcp-scanner claude --plugin-dir /path/to/claude-code-plugin
Quoted from claude-code-plugin/README.md#L18-32 at the pinned commit; a quotation, not a command to copy.

Run it with least privilege

claude code
run the yara analyzer only (no API keys, no cloud upload); avoid --scan-known-configs and the stdio launch mode unless you trust every server in your local configs; remove scanner and LLM API keys from the environment before a known-configs scan, because every started server inherits it
note
derived from the code; of it, the lab ran the YARA-only CLI without keys (runs/2026-11-07), not the plugin path

derived, not tested: proposed from the code analysis

End of the card. Below: what we checked, and what we found.MarkdownJSON

The record · every value with its evidence

What we checked, and what we found.

Profile read at commit 5d147dc on 2026-10-25: 60 facts, each with its quoted line confirmed by script; see the lab runs below.Each fact was read from the tool's files at the checked version and links to the line it comes from. Where nothing was found, the page says so instead of assuming “none”.

Run and written by Ilja Schlak, 2026-11-07. Each section opens with the answer; the file and line of every fact follow it.

What it can change the capability groups as upstream groups them, worst first

Changes, runs commands, sends data out, according to the capabilities read.

Partly listed: CLI features the plugin does not wrap: virustotal, pypi-scan, npm-scan (Docker), vulnerable-package --fix, readiness, prompt_defense, meta, REST API server

What it can do, by group
GroupWhat it coversEffectOn by default
quick-scan, scan-remoteRun mcp-scanner with the YARA analyzer against a remote MCP server URL and report a summary (quick-scan) or details (scan-remote). quick-scan.md L9-13, claude-code-plugin/commands/quick-scan.md#L9-13 at the checked commitreads, runs commandsyes
deep-scanRun the YARA, LLM and Cisco AI Defense API analyzers against a remote MCP server and report findings by severity. deep-scan.md L11, claude-code-plugin/commands/deep-scan.md#L11 at the checked commitreads, runs commands, sends data outyes
scan-known-configsScan the servers defined in the well-known MCP config files of Windsurf, Cursor, Claude Desktop and VS Code with the YARA analyzer. scan-known-configs.md L11-18, claude-code-plugin/commands/scan-known-configs.md#L11-18 at the checked commitreads, runs commandsyes
scan-configScan every MCP server defined in one config file given by path with the YARA analyzer. scan-config.md L11, claude-code-plugin/commands/scan-config.md#L11 at the checked commitreads, runs commandsyes
scan-prompts, scan-resourcesFetch the prompts or resources of a remote MCP server and check them with the LLM analyzer. scan-prompts.md L11, claude-code-plugin/commands/scan-prompts.md#L11 at the checked commitreads, runs commands, sends data outyes
scan-behavioralAnalyze MCP server source code in a file or directory for docstring-versus-implementation mismatches with the LLM-backed behavioral analyzer. scan-behavioral.md L14-19, claude-code-plugin/commands/scan-behavioral.md#L14-19 at the checked commitreads, runs commands, sends data outyes
mcp-security-scanSkill Claude uses on MCP security requests; adds launching and scanning stdio MCP servers, server-instruction scans and combined analyzers to the commands. SKILL.md L74-75, claude-code-plugin/skills/security-scan/SKILL.md#L74-75 at the checked commitreads, runs commands, sends data outyes
pypi-scan, npm-scanDownload a PyPI or npm package and scan it with behavioral analysis, inside a Docker sandbox by default or in-process with --no-docker. README.md L289-290, README.md#L289-290 at the checked commitreads, runs commandsyes
vulnerable-packageCheck a requirements file or project for known vulnerable Python dependencies using PyPI or OSV data; --fix changes the vulnerable dependencies automatically. README.md L531-540, README.md#L531-540 at the checked commitreads, changesyes

Where it sends data and who can connect to it

7 outside connections found in the files read: Remote MCP server (named URL), Remote servers listed in client configs, LLM provider via LiteLLM, Cisco AI Defense inspect API, Package registries of launched servers, mcp.deepwiki.com, VirusTotal.

One listener in the files read.

Other connections not ruled out: read in the documentation and the cited code, not searched in full.

How it runs generated from the files read, never drawn by hand

Markdown slash commands and a skill in Claude Code have the model run the local mcp-scanner Python CLI; the CLI reaches remote MCP servers over SSE or streamable HTTP, starts stdio servers as child processes, and can send content to an LLM provider via LiteLLM or to the Cisco AI Defense API. SKILL.md L35, claude-code-plugin/skills/security-scan/SKILL.md#L35 at the checked commit

Your AI client

Parts that live inside the AI client: skill instructions, client configuration.

Your machine

Programs and files on the machine where you run the tool.

Outside your machine

Remote services: vendor APIs, model providers, targets, telemetry endpoints. Data sent here leaves your machine.

The six rights, read three waysThe six rights a tool can take (files, network, execution, secrets, persistence, approval), each read three ways and rated 0 to 3. 0 never means safe; “?” means no evidence. what the author says, what the code shows, what one lab run showed

Level 3 (privileged), read from the code.

Privilege Reach: six rights, each read three ways. Levels 0 to 3; ? means no evidence.
RightAuthor sayswhat the author saysCode showswhat static analysis findsRun showedwhat one lab run showed
Fileswhere does it read and write?
Networkwhom does it talk to?
Executionwhat does it run?
Secretswhich credentials does it touch?
Persistencewhat survives the run?
Approvaldoes it ask before acting?

0 contained · 1 scoped · 2 open · 3 privileged · ? no evidence · 0 never means safe · zero means: none declared (Declared), none found (Code), none observed (Lab)

Author says: the evidence

  • Files · 1SKILL.md L62-66 author lists the home-directory MCP client config files the known-config scan reads
  • Network · 1SKILL.md L197-199 author names the Cisco AI Defense API endpoint for the api analyzer
  • Execution · 2SKILL.md L74-89 author documents that the scanner launches a user-chosen stdio server command
  • Secrets · 3SKILL.md L213-216 author documents authenticating the LLM analyzer with a named AWS profile, which reads the local AWS credential store

Code shows: the evidence

  • Files · 1SKILL.md L53-66 the known-config scan reads MCP client configs in the home directory, outside the working directory
  • Network · 2SKILL.md L58-59 the known-configs scan connects to every remote MCP server listed in local client configs, hosts the user does not name
  • Execution · 2SKILL.md L87-89 the skill tells the agent to launch any program as a stdio MCP server
  • Secrets · 3scan-known-configs.md L11-18 the command reads the MCP client configuration files of Windsurf, Cursor and Claude Desktop, which can hold server API keys and tokens
  • Persistence · 2README.md L16-18 the documented prerequisite installs the scanner package into the active Python environment
  • Approval · ?no evidence: the skill and command frontmatter set no allowed-tools, permission mode or auto-approve, so the approval posture cannot be read statically

Valid for commit 5d147dc (v4.8.6) · checked 2026-11-07 · method reach-v0.1The published rules we follow: how tools are selected, how their rights are read and rated, how a lab run is done.

Limits and risks what the files say that fits nowhere else, and what this reading does not cover

What you need and what the documented installer does

What you need
KindWhat
AI clientClaude Code
RuntimeClaude Code, which loads the plugin from its folder with --plugin-dir. README.md L32, claude-code-plugin/README.md#L32 at the checked commit
Other toolsThe cisco-ai-mcp-scanner Python package, installed separately from the plugin. README.md L16-18, claude-code-plugin/README.md#L16-18 at the checked commit
RuntimePython 3.11.4 or newer. pyproject.toml L16, pyproject.toml#L16 at the checked commit
Other toolsuv, because the skill tells Claude to start the scanner with uv run mcp-scanner. SKILL.md L10, claude-code-plugin/skills/security-scan/SKILL.md#L10 at the checked commit
Model keyMCP_SCANNER_LLM_API_KEY for the llm and behavioral analyzers used by deep-scan, scan-prompts, scan-resources and scan-behavioral. README.md L67-68, claude-code-plugin/README.md#L67-68 at the checked commit
CredentialsMCP_SCANNER_API_KEY for the Cisco AI Defense api analyzer. README.md L69, claude-code-plugin/README.md#L69 at the checked commit
AccountA Cisco AI Defense subscription for the api analyzer. README.md L814, README.md#L814 at the checked commit

What the documented installer does

Lab runs (1) one run is an observation, not a benchmark

Lab run 2026-11-07

One run is an observation, not a benchmark.

The lab values hold for exactly this configuration: commit 5d147dc (v4.8.6), the runtime below.

Setup

Target
Lab fixture vuln-mcp-server (MCP over streamable HTTP) 0.1.0
Model
none (the tool ran without a model)
Client
Standalone (own model access) n/a (no agent client), mode n/a (no approval layer)
Access
white-box
Task
Run without a model: install the Cisco mcp-scanner CLI, start it in YARA-only mode against the prepared MCP server and observe the scanner's reach and any egress. Expected: a connection to the target only, no egress to the internet.
Timebox
10 min
Duration
2:38

Result

Reported
3 findings
Validated
sample of 3: 3 true, 0 false positives
Score
At tool level all 3 baited tools were flagged HIGH and both clean controls stayed SAFE. The prompt and server-instruction probes were not scanned: the remote scan lists tools only.
Scope violations
none
Notes
A small synthetic sample from a lab fixture, so no general detection rate follows: coverage 3 of 5 probes, recall 1.0 on the scanned ones (score.json). Even in YARA-only mode without keys the scanner tries at start-up to download litellm's model cost map from GitHub (tool-stderr.txt line 2). The lab resolver answered that name with its sinkhole (dns.jsonl line 1), the connection attempts were dropped (blocked.jsonl), and the scan began about six seconds after the tool started: tool start 13:02:35 (host-events.jsonl line 4), first request 13:02:41 (target-access.txt line 2). During the install phase the same host was requested once through the lab proxy, one second after the last package download, and refused (install-egress.jsonl line 202). The install took the 99 locked packages with their hashes from the project's uv.lock.

What it did, per right

  • Files · ?no evidence: no writes besides result paths (fs-diff.json); reads are not audited, so 0 (reads only the working directory) and 1 (reads outside) cannot be told apart; /tmp in the runner is a tmpfs and invisible to fs-diff
  • Network · 2 talks to any host
    beyond declared
    blocked.jsonl#L1-5 the runner (10.73.2.10) tried five times, a second apart, to connect to 198.18.0.1:443, the lab's DNS sinkhole, and was dropped (line 1 lies half a second before the tool start the host recorded, because the lab machines' clocks differ by about a second){"timestamp": "2026-11-07T13:02:34.537212", "dvc": "Netfilter", "raw.pktlen": 60, "raw.pktcount": 1, "oob.prefix": "gw-drop-fwd ", "oob.time.sec": 1794056554, "oob.time.usec": 537212, "oob.mark": 0, "oob.ifindex_in": 4, "oob.ifindex_out": 2, "oob.hook": 2, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 1, "raw.mac.addrlen": 6, "ip.protocol": 6, "ip.tos": 0, "ip.ttl": 63, "ip.totlen": 60, "ip.ihl": 5, "ip.csum": 55634, "ip.id": 36867, "ip.fragoff": 16384, "src_port": 45344, "dest_port": 443, "tcp.seq": 2585627822, "tcp.ackseq": 0, "tcp.window": 64240, "tcp.offset": 0, "tcp.reserved": 0, "tcp.urg": 0, "tcp.ack": 0, "tcp.psh": 0, "tcp.rst": 0, "tcp.syn": 1, "tcp.fin": 0, "tcp.res1": 0, "tcp.res2": 0, "tcp.csum": 53908, "src_ip": "10.73.2.10", "dest_ip": "198.18.0.1"}{"timestamp": "2026-11-07T13:02:35.555233", "dvc": "Netfilter", "raw.pktlen": 60, "raw.pktcount": 1, "oob.prefix": "gw-drop-fwd ", "oob.time.sec": 1794056555, "oob.time.usec": 555233, "oob.mark": 0, "oob.ifindex_in": 4, "oob.ifindex_out": 2, "oob.hook": 2, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 1, "raw.mac.addrlen": 6, "ip.protocol": 6, "ip.tos": 0, "ip.ttl": 63, "ip.totlen": 60, "ip.ihl": 5, "ip.csum": 55633, "ip.id": 36868, "ip.fragoff": 16384, "src_port": 45344, "dest_port": 443, "tcp.seq": 2585627822, "tcp.ackseq": 0, "tcp.window": 64240, "tcp.offset": 0, "tcp.reserved": 0, "tcp.urg": 0, "tcp.ack": 0, "tcp.psh": 0, "tcp.rst": 0, "tcp.syn": 1, "tcp.fin": 0, "tcp.res1": 0, "tcp.res2": 0, "tcp.csum": 53908, "src_ip": "10.73.2.10", "dest_ip": "198.18.0.1"}{"timestamp": "2026-11-07T13:02:36.579310", "dvc": "Netfilter", "raw.pktlen": 60, "raw.pktcount": 1, "oob.prefix": "gw-drop-fwd ", "oob.time.sec": 1794056556, "oob.time.usec": 579310, "oob.mark": 0, "oob.ifindex_in": 4, "oob.ifindex_out": 2, "oob.hook": 2, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 1, "raw.mac.addrlen": 6, "ip.protocol": 6, "ip.tos": 0, "ip.ttl": 63, "ip.totlen": 60, "ip.ihl": 5, "ip.csum": 55632, "ip.id": 36869, "ip.fragoff": 16384, "src_port": 45344, "dest_port": 443, "tcp.seq": 2585627822, "tcp.ackseq": 0, "tcp.window": 64240, "tcp.offset": 0, "tcp.reserved": 0, "tcp.urg": 0, "tcp.ack": 0, "tcp.psh": 0, "tcp.rst": 0, "tcp.syn": 1, "tcp.fin": 0, "tcp.res1": 0, "tcp.res2": 0, "tcp.csum": 53908, "src_ip": "10.73.2.10", "dest_ip": "198.18.0.1"}{"timestamp": "2026-11-07T13:02:37.603228", "dvc": "Netfilter", "raw.pktlen": 60, "raw.pktcount": 1, "oob.prefix": "gw-drop-fwd ", "oob.time.sec": 1794056557, "oob.time.usec": 603228, "oob.mark": 0, "oob.ifindex_in": 4, "oob.ifindex_out": 2, "oob.hook": 2, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 1, "raw.mac.addrlen": 6, "ip.protocol": 6, "ip.tos": 0, "ip.ttl": 63, "ip.totlen": 60, "ip.ihl": 5, "ip.csum": 55631, "ip.id": 36870, "ip.fragoff": 16384, "src_port": 45344, "dest_port": 443, "tcp.seq": 2585627822, "tcp.ackseq": 0, "tcp.window": 64240, "tcp.offset": 0, "tcp.reserved": 0, "tcp.urg": 0, "tcp.ack": 0, "tcp.psh": 0, "tcp.rst": 0, "tcp.syn": 1, "tcp.fin": 0, "tcp.res1": 0, "tcp.res2": 0, "tcp.csum": 53908, "src_ip": "10.73.2.10", "dest_ip": "198.18.0.1"}{"timestamp": "2026-11-07T13:02:38.627275", "dvc": "Netfilter", "raw.pktlen": 60, "raw.pktcount": 1, "oob.prefix": "gw-drop-fwd ", "oob.time.sec": 1794056558, "oob.time.usec": 627275, "oob.mark": 0, "oob.ifindex_in": 4, "oob.ifindex_out": 2, "oob.hook": 2, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 1, "raw.mac.addrlen": 6, "ip.protocol": 6, "ip.tos": 0, "ip.ttl": 63, "ip.totlen": 60, "ip.ihl": 5, "ip.csum": 55630, "ip.id": 36871, "ip.fragoff": 16384, "src_port": 45344, "dest_port": 443, "tcp.seq": 2585627822, "tcp.ackseq": 0, "tcp.window": 64240, "tcp.offset": 0, "tcp.reserved": 0, "tcp.urg": 0, "tcp.ack": 0, "tcp.psh": 0, "tcp.rst": 0, "tcp.syn": 1, "tcp.fin": 0, "tcp.res1": 0, "tcp.res2": 0, "tcp.csum": 53908, "src_ip": "10.73.2.10", "dest_ip": "198.18.0.1"}
    dns.jsonl#L1 the runner asked for raw.githubusercontent.com and was given the sinkhole address{"ts": "2026-11-07T13:02:34Z", "client": "10.73.2.10", "port": 46072, "qtype": "A", "name": "raw.githubusercontent.com", "outcome": "sinkhole", "answers": ["198.18.0.1"], "upstream": null, "log_line": 24}
    tool-stderr.txt#L2 the scanner logs that its litellm dependency could not fetch the model cost map from raw.githubusercontent.com and fell back to a local copy13:02:41 - LiteLLM:WARNING: get_model_cost_map.py:290 - LiteLLM: Failed to fetch remote model cost map from https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json: timed out. Falling back to local backup.
    gateway-sets.txt#L2-5 no external target was allowed during the run (run_allow has no elements) set run_allow { type ipv4_addr flags interval }
    target-access.txt#L2-4 the scan itself reached only the declared target (run->tgt)2026-11-07T13:02:41+00:00 10.73.2.10 POST methods=initialize2026-11-07T13:02:41+00:00 10.73.2.10 POST methods=notifications/initialized2026-11-07T13:02:41+00:00 10.73.2.10 POST methods=tools/list
  • Execution · 0 runs no programsnone found: no execve besides the tool itself. In host-events.jsonl lines 1 to 3 are the lab harness (timeout, the start wrapper and a uname the wrapper runs before handing over), line 4 is the tool starting (python3 running mcp-scanner), and nothing was started after it
  • Secrets · 0 touches no credentialsnone found: no reads of the watched credential stores (auditd: SSH, cloud CLIs, Kubernetes, GnuPG, browser profiles, Docker, netrc, npmrc, pypirc, agent tokens, /etc/shadow, sudoers), which include the three canary files planted for this run (AWS credentials, netrc, npmrc); no canary in egress.jsonl or dns.jsonl. Environment variables are not observable
  • Persistence · 0 leaves results onlynone found: no persistence paths in fs-diff.json (outside the lab's churn filter) and no writes to the watched start-up files (shell rc, autostart, systemd --user)
  • Approval · ?no evidence: no approval events, the CLI ran without an agent client or an approval layer

Lab verdict

Beyond declared on 1 of 6 rights: network (observed 2, declared 1), with blocked attempts to reach GitHub at start-up even in YARA-only mode.

Fit
partial (our judgement whether the reach fits the task)
Use again
with limits
In one sentence
Useful as a key-free first pass over an MCP server's tools: it flagged all three baited tools without a false alarm, but it reads tools only and reaches for GitHub at start-up.
Limits
Measured only in YARA-only mode against one small synthetic fixture, so no detection rate follows. The default remote scan lists tools only: prompts, resources and server instructions stay unscanned. At start-up the scanner fetches a model price list from GitHub that it does not need for a YARA scan; run it without internet access or behind an allowlist, where the fetch fails and the scan goes on with the bundled copy, as observed. The API and LLM analyzers, the known-configs scan and the stdio launch mode were not run and keep the code reading.

Tested minimal configuration

cli
mcp-scanner --log-level error --analyzers yara --format raw --server-url <target URL>, without API keys and without cloud upload (tool-cmd.sh)

Incidents

0 real-time alerts · blocked.jsonl lines 1 to 5: SYN packets from the runner to the lab's DNS sinkhole on port 443, all dropped; install-egress.jsonl line 202: a CONNECT to raw.githubusercontent.com during the install phase, refused by the lab proxy (403) · run not aborted

Recording

No recording: a stand-alone tool started by the lab harness has no interactive session. Its call and output are listed with the artifacts below.

Artifacts with SHA-256 (15 files)
  • blocked.jsonlfa4c5b8f74ea463aac65fb397b57cdf0be07dae689dd7e885d292da586bb14fc
  • declared.json533c113c0389ad9ef26e7d79419bc8211479489182f60b37cd3c1fb1dbfaa2f1
  • dns.jsonl06554466cecd14c4f098eaa7a3154bd93f085bdf65c47463b3b03c670dcf820f
  • egress.jsonle3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  • findings.jsonl38c975b0cb6407806f9a23a4b1d1b24f11467634cc9b6964efa0b3620dbd74f4
  • fs-diff.json10adc8307b205ac94c44019718c7a166b86cb293e41e06f52eec1954af8d8730
  • gateway-sets.txtc4da9ef400e835150075596c3c302b3875c13c176e18b16c50872f420e59d4e0
  • hitl-events.jsonle3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  • host-events.jsonla76168c86c8c100c9c3afd51bb859cb89cf1087c908213d548bd137d8fed64d5
  • install-egress.jsonl688725a12db77153a69cdccafdbf46a8410b5f4e2290edaadb2ebfb5397aaf2f
  • scanner-output.json0812f899fd38cf50b70f21a07fd6dc7a6b87d807cc461bbb844c9f990bca966c
  • score.json7412f736197ed83df079596623f9d03df4586a3cd7ffef4f530af8a5ba9af925
  • target-access.txt2dc1685123597a36321643a56e66a7111812b87095df9385b4d8954238c5f2b8
  • tool-cmd.sh0fbcb2b8d1763bfbe48551ac23f31617b44acb8e5eb80c86a2784c9b88030507
  • tool-stderr.txt0de3bb8622c0289de4f199e8fab47ccade21577281c958c78779c90d4cb8dff1
  • manifest.jsonlists the hashes above

Secret scan: not run: not installed on the lab host; the scan above instead (2026-11-07); bait texts of the lab fixture in scanner-output.json replaced by their SHA-256, ANSI colour codes and CRLF removed from tool-stderr.txt, the host path removed from score.json, only the two allow sets of the gateway ruleset published (gateway-sets.txt); scan of all published files by analysis/export-package.py for this run's canary values, the original bait texts, AWS keys, private keys, API tokens and host identifiers: no hits. Not published: pcap/, diff/, raw/runner-audit.log, raw/tool-stdout.txt, raw/canaries.txt, raw/seed/, raw/fs-diff-raw.csv, preflight.log, preflight.json, profile.yaml, task.txt, allowlist.txt, approver-policy.json, proxy-policy.json, sensors/gw-nft.txt, sensors/egress.flows, sensors/dns.log, sensors/install-dns.log, sensors/install-fs-diff.json.

Interests. Private project, privately funded. The author is employed by an IT consultancy; the company is neither client nor sponsor of this measurement and had no influence on selection, execution or result. No business relationship with the maintainers of the tested tool; no credits, licences or payments accepted from tested vendors. Deviations are stated in this field.

Right of reply: dispute process. Replications: none yet.

About this entry

Type
Plugin · Agent security · works with Claude Code
Source
github.com/cisco-ai-defense/mcp-scanner · claude-code-plugin · Apache-2.0 · manifest plugin.json
Version readThe install command installs exactly the version we checked (the pinned git commit), so what you get is what the card describes.
5d147dc · v4.8.6 · last upstream push 2026-10-16 · no release since the pinned commit (current v4.8.6)
In the catalog
tried · added 2026-10-19 · last checked 2026-11-07 · next check 2027-05-06 · fresh
ScannersA scan of the tool's files with a scanner for malicious patterns. “Pending” means it has not run yet.
cisco-skill-scanner: not run, pending
Changes
1 change to published values, the last on 2026-11-07: see Changes
MethodThe published rules we follow: how tools are selected, how their rights are read and rated, how a lab run is done.
v0.1 · reach-v0.1 · badge · the rules

Disagree?

Dispute a value with evidence (file, line, commit): write to hello@readbeforerun.ai. A dispute is checked against the pinned commit; a changed value is logged under Changes.

How this entry was checked, and how to cite it

Selected by the published criteria (method v0.1). What the author says comes only from author statements; what the code shows comes from the code and manifests at commit 5d147dc, each with one evidence line. A “?” means no evidence, never zero; zero never means safe. The lab run shows what happened in exactly one configuration; it is a lower bound, not a benchmark.

The descriptive profile (what it does, can do, how it runs, what it needs) was read through the same isolated pipeline at commit 5d147dc on 2026-10-25: one reader proposed every fact with a quoted line, a script confirmed each quoted line (60 of 60), and a second reader checked each sentence against its lines. Where nothing was found, the page says so instead of assuming “none”.

Known issues and limits: remote server-side behaviour stays “?”; the lab is not your production; static analysis can miss runtime behaviour.

Placement, badges or fast tracks are not for sale. The author is employed by an IT consultancy; the company has no influence on selection, execution or result.

Cite this:

Ilja Schlak. "Cisco MCP Scanner Plugin". Agentic Security Field Guide, checked 2026-11-07, method reach-v0.1. https://readbeforerun.ai/catalog/cisco-mcp-scanner/

The method · the rules

For maintainers

Badge for your README (reach 3 · beyond declared (1)):

[![reach 3 · beyond declared (1)](https://readbeforerun.ai/badge/cisco-mcp-scanner.svg)](https://readbeforerun.ai/catalog/cisco-mcp-scanner/)

Dispute a value with evidence (file, line, commit): write to hello@readbeforerun.ai. A dispute is checked against the pinned commit; a changed value is logged under Changes.

Claim the entry with a fieldguide.yaml in your repository: planned.

Other tools for the same task

Task: Agent supply-chain scan. The task pages compare every tool side by side.
  1. 012102
    Trail of Bits Agentic Actions AuditorPlugin · by trailofbits · reach 2, openDraft · awaiting review

    Claude Code plugin that statically audits GitHub Actions workflows which invoke AI coding agents for injection and permission flaws.

    Can run shell commands or eval · run with broad pre-approvals · not run yet · checked 2026-10-19

    Code shows