# 🛡️ AI Agent & MCP Security Scanner (`inexhaustible_glass/agent-security-scanner`) Actor

Scan GitHub repos for AI-agent, MCP-server & skill security risks: prompt injection, tool poisoning, hallucinated packages, secrets & dangerous code.

- **URL**: https://apify.com/inexhaustible\_glass/agent-security-scanner.md
- **Developed by:** [Hitman studio](https://apify.com/inexhaustible_glass) (community)
- **Categories:** AI, Agents, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## 🛡️ AI Agent & MCP Security Scanner

**Scan any GitHub repo for AI-agent, MCP-server & agent-skill security risks — before you connect it to Claude Code, Cursor, or Windsurf.**

Point it at a repo (or many) and get a clean, structured security report. Built for **both humans** (readable report) **and AI agents** (call it via the Apify API / as an MCP tool → structured JSON).

### What it detects

| Category | What it catches |
|---|---|
| 🧬 **MCP tool poisoning** | Hidden/adversarial instructions inside MCP tool descriptions (the #1 MCP attack) |
| 👻 **Hidden Unicode** | Zero-width / bidi / tag characters that hide instructions from human review |
| 💊 **Hallucinated packages** | npm/PyPI dependencies that **don't exist** on the registry (LLM-invented, squat bait) |
| 🎭 **Typosquat packages** | Dependencies one character away from a hugely popular package |
| ⚡ **Dangerous code** | `eval` / `exec` / `os.system` / `child_process` / `shell=True` / unsafe pickle & yaml |
| 🌐 **Runtime fetch-&-exec** | Code that downloads remote text/instructions and executes them |
| 💉 **Prompt injection** | Jailbreak strings + user input concatenated into system prompts |
| 🔩 **MCP config risk** | MCP servers that spawn a raw shell or auto-run remote packages (`npx -y`) |
| 🔑 **Exposed secrets** | Hardcoded OpenAI / Anthropic / GitHub / AWS / Google / Slack keys |

### Output

Per repo you get a **security score (0–100)**, a **grade (A–D)**, a **verdict (ALLOW / WARN / BLOCK)**, findings grouped by category, and every finding with file, line, severity and a snippet.

```json
{
  "repo": "owner/repo",
  "security_score": 46,
  "grade": "D — high risk",
  "verdict": "BLOCK",
  "high_severity": 4,
  "medium_severity": 2,
  "findings_by_category": { "mcp_tool_poisoning": 1, "dangerous_code": 3, "hallucinated_package": 1 },
  "findings": [ { "file": "server.py", "line": 42, "category": "dangerous_code", "severity": "high", "title": "os.system() shell call", "snippet": "..." } ]
}
````

### Input

```json
{
  "repoUrls": ["https://github.com/owner/repo", "owner/another-repo"],
  "maxFiles": 400
}
```

- **repoUrls** — public GitHub repos (full URL or `owner/repo`).
- **githubToken** *(optional)* — raises the API limit 60→5000/hr for scanning many repos.
- **maxFiles** *(optional)* — cap files scanned per repo.

### 🤖 Use it from an AI agent (MCP / API)

This Actor is built for AI agents too. An assistant like **Claude Code, Cursor, or Windsurf** can call it as a pre-flight safety check before installing an MCP server or skill — the output is machine-readable JSON, and the `verdict` field (`ALLOW` / `WARN` / `BLOCK`) is designed to gate an agent's next action.

Call it over the Apify API:

```bash
curl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"repoUrls":["owner/repo"]}'
```

Or expose it through the **Apify MCP server** so your agent can invoke "scan this repo before I connect to it" as a tool.

### Why

AI agents now pull in MCP servers, skills and packages written by anyone. A single poisoned tool description or a hallucinated package name can hijack your agent or ship malware. This scanner gives you a fast, free pre-flight check on any repo — 100% public data, no code execution, no paid APIs.

***

**Keywords:** MCP security scanner · AI agent security · prompt injection detection · MCP tool poisoning · package hallucination · typosquat detection · supply chain security · Claude Code security · Cursor MCP · Windsurf · LLM security · agent skill audit · secrets scanning · GitHub repo security scan · model context protocol · agentic AI security · code security scanner · devsecops for AI agents.

# Actor input Schema

## `repoUrls` (type: `array`):

Public GitHub repos to scan. Accepts full URLs (https://github.com/owner/repo) or 'owner/repo'. These are typically AI agents, MCP servers, or agent skills.

## `githubToken` (type: `string`):

Optional GitHub personal access token — raises the API rate limit from 60/hr to 5000/hr for scanning many repos. Read-only 'public\_repo' scope is enough. Leave empty for small scans.

## `maxFiles` (type: `integer`):

Maximum number of code/config files to scan per repo. Keeps large repos fast.

## Actor input object example

```json
{
  "repoUrls": [
    "https://github.com/modelcontextprotocol/servers"
  ],
  "maxFiles": 400
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "repoUrls": [
        "https://github.com/modelcontextprotocol/servers"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("inexhaustible_glass/agent-security-scanner").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "repoUrls": ["https://github.com/modelcontextprotocol/servers"] }

# Run the Actor and wait for it to finish
run = client.actor("inexhaustible_glass/agent-security-scanner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "repoUrls": [
    "https://github.com/modelcontextprotocol/servers"
  ]
}' |
apify call inexhaustible_glass/agent-security-scanner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=inexhaustible_glass/agent-security-scanner",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "🛡️ AI Agent & MCP Security Scanner",
        "description": "Scan GitHub repos for AI-agent, MCP-server & skill security risks: prompt injection, tool poisoning, hallucinated packages, secrets & dangerous code.",
        "version": "0.1",
        "x-build-id": "HHv4uLWMLGZcn1abJ"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/inexhaustible_glass~agent-security-scanner/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-inexhaustible_glass-agent-security-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/inexhaustible_glass~agent-security-scanner/runs": {
            "post": {
                "operationId": "runs-sync-inexhaustible_glass-agent-security-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/inexhaustible_glass~agent-security-scanner/run-sync": {
            "post": {
                "operationId": "run-sync-inexhaustible_glass-agent-security-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "repoUrls"
                ],
                "properties": {
                    "repoUrls": {
                        "title": "GitHub repositories to scan",
                        "type": "array",
                        "description": "Public GitHub repos to scan. Accepts full URLs (https://github.com/owner/repo) or 'owner/repo'. These are typically AI agents, MCP servers, or agent skills.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "githubToken": {
                        "title": "GitHub token (optional)",
                        "type": "string",
                        "description": "Optional GitHub personal access token — raises the API rate limit from 60/hr to 5000/hr for scanning many repos. Read-only 'public_repo' scope is enough. Leave empty for small scans."
                    },
                    "maxFiles": {
                        "title": "Max files per repo",
                        "minimum": 20,
                        "maximum": 3000,
                        "type": "integer",
                        "description": "Maximum number of code/config files to scan per repo. Keeps large repos fast.",
                        "default": 400
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
