Сканер безопасности для навыков ИИ-агентов. Обнаруживает уязвимости, вредоносные паттерны, риски безопасности, промпт-инъекции, эксфильтрацию данных и риски цепочки поставок в навыках Claude Code, Codex и MCP до их установки.
Сканер безопасности для навыков ИИ-агентов. Обнаруживайте уязвимости, вредоносные паттерны и риски безопасности перед установкой навыков агентов.
Навыки ИИ-агентов (используемые Claude Code, Codex CLI, Gemini CLI и др.) выполняются с неявным доверием и минимальной проверкой. Исследования показывают, что 26,1% навыков содержат уязвимости, а 5,2% демонстрируют вероятное вредоносное намерение.
SkillSpector помогает ответить на вопрос: «Безопасно ли устанавливать этот навык?»
SkillSpector является частью конвейера NVIDIA Verified Skills, который сканирует, оценивает и подписывает навыки агентов перед публикацией. Навыки, прошедшие проверку, публикуются в каталоге навыков NVIDIA.
Уведомление об открытом программном обеспечении: этот проект загрузит и установит дополнительные сторонние проекты с открытым исходным кодом. Ознакомьтесь с условиями лицензий этих проектов перед использованием.
Сначала создайте и активируйте виртуальную среду (все цели make предполагают, что виртуальная среда активна). Используйте uv или pip; Makefile использует uv, если он доступен, в противном случае — pip.
Быстрая установка с uv (только CLI):```bash uv tool install git+https://github.com/NVIDIA/skillspector.git
Если вы планируете запускать `skillspector mcp`, установите дополнительный пакет MCP при установке:```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
From source:```bash
git clone https://github.com/NVIDIA/skillspector.git cd skillspector
uv venv .venv && source .venv/bin/activate
make install
make install-dev
### Docker (Python не требуется)
Запустите SkillSpector без установки Python, собрав его локально из включённого [Dockerfile](https://github.com/nvidia/skillspector/blob/main/Dockerfile). Образ основан на официальном Docker-образе Python `3.12-slim-bookworm`.
**Соберите образ:**```bash
make docker-build
# or: docker build -t skillspector .
Сканирование локальной директории путем монтирования вашей текущей директории в /scan, рабочую директорию контейнера:```bash
docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm
**Сканирование с анализом LLM** путём передачи учётных данных через локальный файл `.env`:```bash
cat > .env <<'EOF'
SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
EOF
pip install pycryptodome
git clone https://github.com/example/repo.git
cd repo
pip install -r requirements.txt
Скопируйте файл .env.example в .env и заполните необходимые значения:
cp .env.example .env
Затем отредактируйте файл .env и укажите свои ключи API и другие параметры конфигурации.
Чтобы убедиться, что всё установлено корректно, выполните:
python -m tool_name --version
Если вы видите номер версии, установка прошла успешно.```bash
docker run --rm
-v "$PWD:/scan"
--env-file .env
skillspector scan ./my-skill/
Или передайте учётные данные напрямую из вашего окружения оболочки:```bash
docker run --rm \
-v "$PWD:/scan" \
-e SKILLSPECTOR_PROVIDER=anthropic \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
skillspector scan ./my-skill/
Запишите отчёт в файловую систему хоста, записав его в смонтированный каталог:```bash
docker run --rm
-v "$PWD:/scan"
skillspector scan ./my-skill/ --no-llm --format json --output report.json
**Необязательный псевдоним** для повторяющихся статических сканирований:```bash
alias skillspector-docker='docker run --rm -v "$PWD:/scan" skillspector'
skillspector-docker scan ./my-skill/ --no-llm
skillspector scan ./my-skill/
skillspector scan ./SKILL.md
skillspector scan https://github.com/user/my-skill
skillspector scan ./my-skill.zip
#### Ограничения размера
SkillSpector применяет два независимых ограничения на удалённые и архивные входные данные, чтобы ограничить влияние чрезмерно больших загрузок и zip-бомб:
- **Ограничение на приём**: `INGEST_MAX_BYTES` (100 МиБ) — применяется к потоковым загрузкам по URL, общему несжатому размеру zip-архивов и использованию диска после клонирования Git-репозиториев.
- **Ограничение на элементы zip**: `INGEST_MAX_ZIP_MEMBERS` (10 000) — ограничивает количество записей в одном zip-архиве.
Обратите внимание, что ограничение анализа в 1 МБ на файл (`MAX_FILE_BYTES`) является отдельным, нижестоящим лимитом: оно ограничивает то, что отдельные анализаторы будут считывать из уже принятого каталога. Ограничения на приём выше ограничивают то, какой объём контента может попасть на диск в первую очередь. Нарушение любого из ограничений на приём приводит к закрытому сбою с ошибкой `IngestLimitExceededError`.
### Форматы вывода```bash
# Terminal output (default) - pretty formatted
skillspector scan ./my-skill/
# JSON output - machine readable
skillspector scan ./my-skill/ --format json --output report.json
# Markdown output - for documentation
skillspector scan ./my-skill/ --format markdown --output report.md
# SARIF output - for CI/CD integration and IDE tooling
skillspector scan ./my-skill/ --format sarif --output report.sarif
Сканируйте целые каталоги навыков параллельно из contrib/batch_scan/:```bash
python -m contrib.batch_scan.batch_scan ./my-skills/ --no-llm
python -m contrib.batch_scan.batch_scan ./my-skills/ --workers 20 -f json -o report.json
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 20
Поддерживает многоязычное обнаружение (zh/ja/ko) и вывод в терминал/JSON/Markdown.
Для LLM-сканирования с более высокой степенью параллелизма настройте несколько API-ключей, следуя
[`.env.example`](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/.env.example) — пул повышает пропускную способность
и отказоустойчивость, при условии, что ключи не разделяют ограничение скорости на уровне аккаунта.
Подробности см. в [руководстве для участников](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/docs).
> **Примечание о поддержке LLM:** Конфигурация по умолчанию ориентирована на DeepSeek как на
> самый дешёвый публичный вариант. DeepSeek-Chat
> [планируется вывести из эксплуатации](https://api-docs.deepseek.com/), и у автора
> нет оборудования для тестирования локальных моделей. Пакетный сканер изначально
> тестировался с OpenAI-совместимыми конечными точками — отсутствие поддержки
> структурированного вывода в DeepSeek потребовало ручных исправлений для JSON-парсинга. Если вы можете
> внести вклад в более универсальный бэкенд (Ollama, vLLM или другой провайдер),
> PR приветствуются.
### Подавление ложных срабатываний (базовая линия)
Подавляйте известные/принятые находки, чтобы оценка риска отражала только нерассмотренные
проблемы, а повторные сканирования выявляли только *новые* находки. См.
[руководство по подавлению](https://github.com/nvidia/skillspector/blob/main/docs/SUPPRESSION.md) для получения полной справочной информации.```bash
# Accept all current findings into a baseline (run once), then commit it.
skillspector baseline ./my-skill/ -o .skillspector-baseline.yaml
# Scan against the baseline — only NEW findings are reported and scored.
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml
# Review what was suppressed (still excluded from the score).
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml --show-suppressed
Базовый файл также может использовать устойчивые к дрейфу glob-правила (по идентификатору правила, пути к файлу или сообщению) — см. .skillspector-baseline.example.yaml.
Точные базовые файлы на основе отпечатков привязаны к доказательствам: изменение сканируемого исходного кода или версии SkillSpector сохраняет находку активной, пока она не будет проверена снова.
Когда выбранный базовый файл или его вывод хранится внутри каталога навыка, SkillSpector исключает этот конкретный файл из анализа содержимого, чтобы его текст подавления не мог создавать находки или попадать в перегенерированные отпечатки; соседние файлы остаются в обычной области сканирования.
Для наилучших результатов настройте совместимую с OpenAI LLM-конечную точку для семантического анализа. Выберите провайдера с помощью SKILLSPECTOR_PROVIDER; хостинговые провайдеры поставляются со встроенными моделями по умолчанию, тогда как CLI-провайдеры используют модель по умолчанию локальной среды выполнения, если не задан SKILLSPECTOR_MODEL. SkillSpector также работает с локальными серверами, совместимыми с OpenAI (Ollama, vLLM, llama.cpp), и управляемыми шлюзами вывода.
Провайдер (SKILLSPECTOR_PROVIDER) | Переменная окружения для учётных данных | Конечная точка | Модель по умолчанию |
|---|---|---|---|
openai | OPENAI_API_KEY (+ необязательный OPENAI_BASE_URL) | api.openai.com (или любой URL, совместимый с OpenAI) | gpt-5.4 |
anthropic | ANTHROPIC_API_KEY | api.anthropic.com | claude-opus-4-6 |
anthropic_proxy | ANTHROPIC_PROXY_API_KEY + ANTHROPIC_PROXY_ENDPOINT_URL | Любой прокси в стиле Vertex raw-predict | claude-sonnet-4-6 |
bedrock | AWS_PROFILE (необязательно) + AWS_REGION — SigV4 через boto3 | AWS Bedrock Runtime | us.anthropic.claude-sonnet-4-6-20250915-v1:0 |
nv_build | NVIDIA_INFERENCE_KEY | build.nvidia.com | deepseek-ai/deepseek-v4-flash |
claude_cli | (нет — используется локальная CLI-авторизация) | локальный бинарный файл claude | локальная среда выполнения Claude по умолчанию или SKILLSPECTOR_MODEL |
codex_cli | (нет — используется локальная CLI-авторизация) | локальный бинарный файл codex | локальная среда выполнения Codex по умолчанию или SKILLSPECTOR_MODEL |
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=sk-... skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=anthropic export ANTHROPIC_API_KEY=sk-ant-... skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=anthropic_proxy export ANTHROPIC_PROXY_ENDPOINT_URL=https://my-gateway.example.com/models/claude-sonnet-4-6:streamRawPredict export ANTHROPIC_PROXY_API_KEY=your-bearer-token export SKILLSPECTOR_MODEL=claude-sonnet-4-6 skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=bedrock
export AWS_REGION=us-west-2 # default if unset
skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=nv_build export NVIDIA_INFERENCE_KEY=nvapi-... skillspector scan ./my-skill/
claude auth login sessionexport SKILLSPECTOR_PROVIDER=claude_cli
skillspector scan ./my-skill/
codex login sessionexport SKILLSPECTOR_PROVIDER=codex_cli skillspector scan ./my-skill/
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=ollama export OPENAI_BASE_URL=http://localhost:11434/v1 export SKILLSPECTOR_MODEL=llama3.1:8b skillspector scan ./my-skill/
export SKILLSPECTOR_MODEL=gpt-5.2 skillspector scan ./my-skill/
skillspector scan ./my-skill/ --no-llm
### MCP Server
Запускайте SkillSpector как [Model Context Protocol](https://modelcontextprotocol.io)
сервер, чтобы любой агент с поддержкой MCP (Claude Code, Codex CLI, Gemini CLI) или удалённая
среда выполнения мог вызывать сканирование как инструмент и **блокировать установку навыков/MCP на основе
результата** — превращая SkillSpector в защитный барьер времени выполнения вместо
внеполосного этапа аудита.
`skillspector mcp` требует `skillspector[mcp]`.```bash
# Install, or reinstall if you already used the CLI-only path
uv tool install --force 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
# FastMCP stdio transport for local CLI agents
skillspector mcp
# streamable HTTP/SSE transport for remote / A2A callers
skillspector mcp --transport http --host 127.0.0.1 --port 8000
Транспорт stdio — это текущий путь FastMCP для локальных CLI-агентов, и зависание при инициализации, о котором сообщалось в issue #199, по-прежнему актуально для него.
Сервер предоставляет один инструмент:
scan_skill(target, use_llm=true, output_format="json") — сканирует Git
URL, файловый URL, .zip, .md-файл или каталог и возвращает структурированный
вердикт: risk_score (0-100), severity, recommendation,
safe_to_install и findings. Также сообщает llm_used / scan_mode,
чтобы низкий балл от сканирования только со статическим анализом никогда не был принят за чистый полный скан.Зарегистрируйте его в Claude Code через:```bash claude mcp add skillspector -- skillspector mcp
> **Безопасность — модель доверия HTTP-транспорта**
>
> HTTP-транспорт поставляется **без аутентификации**. Любой вызывающий код, который
> может получить доступ к порту, может вызвать `scan_skill`. Через stdio или `127.0.0.1` это
> та же граница доверия, что и у CLI. Если вы привязываете сервер к маршрутизируемому интерфейсу:
>
> - Разместите сервер за аутентифицирующим обратным прокси (например, nginx + mTLS)
> перед тем, как открыть его для внешнего доступа.
> - Локальные пути и URL-адреса `file://` **автоматически отклоняются** через HTTP, чтобы
> предотвратить чтение произвольных файлов хоста неаутентифицированными вызывающими кодами. Принимаются только
> удалённые Git- и `.zip`-URL-адреса.
## Паттерны уязвимостей
SkillSpector обнаруживает **71 паттерн уязвимостей** в 17 категориях:
### Инъекция промптов (6 паттернов)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| P1 | Переопределение инструкций | ВЫСОКАЯ | Команды игнорировать ограничения безопасности |
| P2 | Скрытые инструкции | ВЫСОКАЯ | Вредоносные директивы в комментариях/невидимом тексте |
| P3 | Команды эксфильтрации | ВЫСОКАЯ | Инструкции по внешней передаче контекста |
| P4 | Манипуляция поведением | СРЕДНЯЯ | Тонкие инструкции, изменяющие решения агента |
| P5 | Вредоносный контент | КРИТИЧЕСКАЯ | Инструкции, которые могут причинить физический вред |
| P9 | Заполнение пробелами | СРЕДНЯЯ | Большое заполнение пробелами, скрывающее инструкции ниже/рядом с видимой областью |
### Анти-отказ (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| AR1 | Подавление отказа | ВЫСОКАЯ | Инструкции никогда не отказывать или всегда соглашаться (например, «никогда не отказывай», «всегда соглашайся») |
| AR2 | Подавление дисклеймеров | ВЫСОКАЯ | Инструкции опускать предупреждения, дисклеймеры или этические комментарии (например, «без дисклеймеров», «не морализируй») |
| AR3 | Аннулирование политики безопасности | ВЫСОКАЯ | Jailbreak-формулировки, аннулирующие защитные механизмы (например, «у тебя нет ограничений», «игнорируй свои правила», «делай что угодно сейчас») |
### Эксфильтрация данных (4 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| E1 | Внешняя передача | СРЕДНЯЯ | Отправка данных на внешние URL-адреса |
| E2 | Сбор переменных окружения | ВЫСОКАЯ | Перечисление, копирование или поиск данных окружения для сбора секретов |
| E3 | Перечисление файловой системы | СРЕДНЯЯ | Сканирование каталогов на предмет чувствительных файлов |
| E4 | Утечка контекста | ВЫСОКАЯ | Внешняя передача контекста разговора |
### Повышение привилегий (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| PE1 | Чрезмерные разрешения | НИЗКАЯ | Запрос доступа сверх заявленной функциональности |
| PE2 | Выполнение sudo/root | СРЕДНЯЯ | Вызов повышенных системных привилегий |
| PE3 | Доступ к учётным данным | ВЫСОКАЯ | Чтение SSH-ключей, токенов, паролей |
### Цепочка поставок (9+ паттернов)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| SC1 | Незакреплённые зависимости | НИЗКАЯ | Отсутствие ограничений версий пакетов |
| SC2 | Загрузка внешних скриптов | ВЫСОКАЯ | curl \| bash и удалённое выполнение кода |
| SC3 | Обфусцированный код | ВЫСОКАЯ | Выполнение кода в кодировке Base64/hex |
| SC4 | Известные уязвимые зависимости | ВЫСОКАЯ | Зависимости с известными CVE (живой поиск OSV.dev) |
| SC5 | Заброшенные зависимости | СРЕДНЯЯ | Неподдерживаемые пакеты без обновлений безопасности |
| SC6 | Тайпсквоттинг | ВЫСОКАЯ | Имена пакетов, похожие на популярные пакеты |
| SC8 | Поставляемый байткод Python | ВЫСОКАЯ | Наличие `__pycache__` / `.pyc` (обход при обнаружении; обход вредоносным байткодом) |
| SC9 | Скрытый исполняемый артефакт | ВЫСОКАЯ | Исполняемый файл, вложенный в контейнер документа или скрытый/замаскированный артефакт |
### Чрезмерная автономия (5 паттернов)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| EA1 | Неограниченный доступ к инструментам | ВЫСОКАЯ | Беспрепятственный доступ к инструментам без ограничений |
| EA2 | Автономное принятие решений | ВЫСОКАЯ | Решения с высоким влиянием без участия человека в цикле |
| EA3 | Расширение области действия | СРЕДНЯЯ | Возможности, выходящие за пределы заявленного назначения |
| EA4 | Неограниченный доступ к ресурсам | СРЕДНЯЯ | Отсутствие лимитов скорости или квот на потребление ресурсов |
| EA5 | Выбор внешней модели или провайдера | СРЕДНЯЯ/ВЫСОКАЯ | Привязки моделей/провайдеров или вызовы оболочки coding-CLI, которые могут переключать биллинговые аккаунты |
### Обработка вывода (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| OH1 | Непроверенная инъекция вывода | ВЫСОКАЯ | Вывод модели используется без санитизации |
| OH2 | Межконтекстный вывод | СРЕДНЯЯ | Вывод пересекает границы доверия без проверки |
| OH3 | Неограниченный вывод | СРЕДНЯЯ | Отсутствие лимитов на размер вывода или скорость генерации |
### Утечка системного промпта (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| P6 | Прямая утечка | ВЫСОКАЯ | Инструкции, раскрывающие системные промпты или внутренние правила |
| P7 | Косвенное извлечение | СРЕДНЯЯ | Извлечение через перефразирование, перевод или побочные каналы |
| P8 | Эксфильтрация на основе инструментов | ВЫСОКАЯ | Эксфильтрация системных промптов через запись в файлы или сетевые запросы |
### Отравление памяти (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| MP1 | Постоянная инъекция контекста | ВЫСОКАЯ | Контент, предназначенный для сохранения между взаимодействиями |
| MP2 | Заполнение окна контекста | СРЕДНЯЯ | Заполняющий контент, вытесняющий ограничения безопасности |
| MP3 | Манипуляция памятью | ВЫСОКАЯ | Вмешательство в память агента или сохранённое состояние |
### Неправильное использование инструментов (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| TM1 | Злоупотребление параметрами инструмента | ВЫСОКАЯ | Сконструированные параметры для непредусмотренного поведения (shell=True, --force) |
| TM2 | Злоупотребление цепочками | ВЫСОКАЯ | Цепочки инструментов, обходящие отдельные проверки безопасности |
| TM3 | Небезопасные значения по умолчанию | СРЕДНЯЯ | Чрезмерно разрешающие значения по умолчанию (отключённый TLS, отсутствие аутентификации) |
### Вредоносный агент (2 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| RA1 | Самомодификация | КРИТИЧЕСКАЯ | Изменение собственного кода или конфигурации во время выполнения |
| RA2 | Постоянство сеанса | ВЫСОКАЯ | Несанкционированное постоянство через cron-задания или скрипты запуска |
### Злоупотребление триггерами (3 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| TR1 | Чрезмерно широкий триггер | СРЕДНЯЯ | Паттерны триггеров, совпадающие с распространёнными словами |
| TR2 | Триггер теневой команды | ВЫСОКАЯ | Триггеры, затеняющие встроенные команды или другие навыки |
| TR3 | Триггер-приманка по ключевым словам | СРЕДНЯЯ | Общие триггеры, предназначенные для максимизации активации |
### Поведенческий AST (9 паттернов)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| AST1 | Вызов exec() | КРИТИЧЕСКАЯ | Прямой exec(), обеспечивающий произвольное выполнение кода |
| AST2 | Вызов eval() | ВЫСОКАЯ | Прямой eval(), вычисляющий произвольные выражения |
| AST3 | Динамический импорт | ВЫСОКАЯ | \_\_import\_\_(), загружающий произвольные модули во время выполнения |
| AST4 | Вызов subprocess | ВЫСОКАЯ | Выполнение внешних команд через subprocess |
| AST5 | os.system / семейство exec | ВЫСОКАЯ | Команды оболочки через модуль os |
| AST6 | Вызов compile() | СРЕДНЯЯ | Создание объектов кода из строк |
| AST7 | Динамический getattr() | СРЕДНЯЯ | Произвольный доступ к атрибутам с нелитеральными именами |
| AST8 | Опасная цепочка выполнения | КРИТИЧЕСКАЯ | exec/eval в сочетании с динамическим источником (сеть, закодированные данные) |
| AST9 | Рефлексивный приёмник getattr() | ВЫСОКАЯ | Рефлексивный exec через `getattr(os,'system')` / `getattr(builtins,'exec')`, обходящий AST1/AST5 |
### Отслеживание потоков данных (5 паттернов)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| TT1 | Прямой поток данных | ВЫСОКАЯ | Данные напрямую перетекают от источника к приёмнику без санитизации |
| TT2 | Поток данных через переменные | СРЕДНЯЯ | Данные перетекают от источника к приёмнику через промежуточные переменные |
| TT3 | Цепочка эксфильтрации учётных данных | КРИТИЧЕСКАЯ | Учётные данные (переменные окружения, секреты) перетекают к сетевым приёмникам вывода |
| TT4 | Чтение файла в сетевую эксфильтрацию | ВЫСОКАЯ | Содержимое файлов перетекает к сетевым приёмникам вывода |
| TT5 | Внешний ввод в выполнение кода | КРИТИЧЕСКАЯ | Сетевой или пользовательский ввод перетекает к приёмникам exec/eval/subprocess |
### YARA-сигнатуры (4 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| YR1 | Совпадение с вредоносным ПО | КРИТИЧЕСКАЯ | Совпадение с YARA-правилом для известных сигнатур вредоносного ПО |
| YR2 | Совпадение с веб-шеллом | КРИТИЧЕСКАЯ | Совпадение с YARA-правилом для паттернов веб-шеллов |
| YR3 | Совпадение с криптомайнером | ВЫСОКАЯ | Совпадение с YARA-правилом для индикаторов крипто-майнинга |
| YR4 | Совпадение с хакерским инструментом/эксплойтом | ВЫСОКАЯ | Совпадение с YARA-правилом для хакерских инструментов или кода эксплойтов |
### MCP Минимальные привилегии (4 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| LP1 | Незадекларированная возможность | ВЫСОКАЯ | Код использует возможности, не указанные в заявленных разрешениях |
| LP2 | Разрешение с подстановочным знаком | СРЕДНЯЯ | Список разрешений содержит подстановочные знаки (\*, all, full, any) |
| LP3 | Отсутствие объявления разрешений | СРЕДНЯЯ | Поле разрешений отсутствует, но код имеет обнаруживаемые возможности |
| LP4 | Избыточно задекларированное разрешение | НИЗКАЯ | Разрешение задекларировано, но соответствующая возможность кода не найдена |
### MCP Отравление инструментов (4 паттерна)
| ID | Паттерн | Серьёзность | Описание |
|----|---------|----------|-------------|
| TP1 | Скрытые инструкции | ВЫСОКАЯ | Скрытые директивы в метаданных (HTML-комментарии, символы нулевой ширины, base64, data URI) |
| TP2 | Обман с Unicode | ВЫСОКАЯ | Гомоглифы, RTL-переопределения, идентификаторы со смешанными алфавитами в метаданных инструмента |
| TP3 | Инъекция в описание параметров | СРЕДНЯЯ | Паттерны инъекций в определениях параметров (переопределения, системные токены, вредоносные значения по умолчанию) |
| TP4 | Несоответствие описания и поведения | СРЕДНЯЯ | Заявленное описание инструмента не соответствует фактическому поведению кода (на основе LLM) |
Все обнаруженные паттерны перечислены в таблицах выше.
## Оценка риска
### Расчёт оценки
- **КРИТИЧЕСКИЕ проблемы**: +50 баллов
- **ВЫСОКИЕ проблемы**: +25 баллов
- **СРЕДНИЕ проблемы**: +10 баллов
- **НИЗКИЕ проблемы**: +5 баллов
- **Исполняемые скрипты**: множитель 1.3x
### Уровни серьёзности
| Оценка | Серьёзность | Рекомендация |
|-------|----------|----------------|
| 0-20 | НИЗКАЯ | БЕЗОПАСНО |
| 21-50 | СРЕДНЯЯ | ОСТОРОЖНО |
| 51-80 | ВЫСОКАЯ | НЕ УСТАНАВЛИВАТЬ |
| 81-100 | КРИТИЧЕСКАЯ | НЕ УСТАНАВЛИВАТЬ |
## Пример вывода
### Вывод терминала```
SkillSpector Security Report v2.0.0
Skill: suspicious-skill
Source: ./suspicious-skill/
Scanned: 2026-01-29 10:30:00 UTC
Risk Assessment
Metric Value
Score 78/100
Severity HIGH
Recommendation DO NOT INSTALL
Components (3)
File Type Lines Executable
SKILL.md markdown 142 No
scripts/sync.py python 87 Yes
requirements.txt text 3 No
Issues (2)
HIGH: Env Variable Harvesting (E2)
Location: scripts/sync.py:23
Finding: for key, val in os.environ.items():...
Confidence: 94%
Explanation: This code collects environment variables containing
API keys and secrets, then sends them to an external server.
HIGH: External Transmission (E1)
Location: scripts/sync.py:45
Finding: requests.post("https://api.skill.io/env"...
Confidence: 89%
Explanation: Data is being sent to an external server. Combined
with env harvesting above, this indicates credential exfiltration.
| Переменная | Описание | Обязательная |
|---|---|---|
SKILLSPECTOR_PROVIDER | Активный LLM-провайдер: openai, anthropic, anthropic_proxy, bedrock, nv_build, claude_cli, codex_cli или gemini_cli. Хостируемые провайдеры используют значения по умолчанию из встроенного model_registry.yaml; claude_cli и codex_cli используют модель по умолчанию локальной CLI-среды выполнения, если не задана SKILLSPECTOR_MODEL. По умолчанию — nv_build. | Необязательная |
NVIDIA_INFERENCE_KEY | Учётные данные для провайдера nv_build (build.nvidia.com). | Обязательна для LLM-анализа, когда SKILLSPECTOR_PROVIDER=nv_build |
OPENAI_API_KEY | Учётные данные для провайдера OpenAI (SKILLSPECTOR_PROVIDER=openai). Также служит резервом второго уровня в каскаде учётных данных, когда активный провайдер не возвращает учётные данные. | Обязательна для LLM-анализа, когда SKILLSPECTOR_PROVIDER=openai |
OPENAI_BASE_URL | Переопределяет конечную точку OpenAI (например, для указания на Ollama). | Необязательная |
SKILLSPECTOR_REASONING_EFFORT | Необязательная настройка усилия рассуждения, зависящая от провайдера и модели. Непустые значения обрезаются и передаются без изменений; пустое или незаданное значение сохраняет поведение провайдера по умолчанию. | Необязательная |
SKILLSPECTOR_OUTPUT_LANGUAGE | Короткая однострочная метка языка (буквы, цифры, пробелы, _ или -; максимум 64 символа) для читаемого человеком текста LLM-результатов, такого как сообщения, пояснения и рекомендации по устранению. Идентификаторы правил, значения серьёзности, пути, код и другие машиночитаемые значения остаются без изменений. Незаданное, пустое или недопустимое значение сохраняет язык вывода по умолчанию. | Необязательная |
SKILLSPECTOR_TEMPERATURE | Необязательная температура выборки от 0 до 1 для хостируемых провайдеров. Незаданное или пустое значение сохраняет значение по умолчанию провайдера. Более низкие значения могут уменьшить вариативность между запусками, но не гарантируют идентичный вывод. |
CLI-провайдеры (
claude_cli,codex_cli): API-ключ не требуется. Аутентификация полностью управляется собственной сессией входа агентской CLI (claude auth login/codex login). SkillSpector никогда не считывает и не передаёт API-ключи, когда активны эти провайдеры. Подпроцесс запускается в усиленной песочнице: инструменты отключены, без MCP, режим песочницы только для чтения (codex), а непроверенное содержимое навыков доставляется только через stdin.
skillspector scan --help
Options: -f, --format [terminal|json|markdown|sarif] Output format [default: terminal] -o, --output PATH Output file path --no-llm Skip LLM analysis (static only) --yara-rules-dir PATH Extra YARA rules directory -b, --baseline PATH Suppress findings listed in a baseline --show-suppressed List baseline-suppressed findings -V, --verbose Show detailed progress --help Show this message and exit
skillspector baseline [-o FILE] [--no-llm] [--reason TEXT]
## Интеграция SkillSpector
SkillSpector создан для управления другими инструментами (CI-конвейерами, шлюзами установки, интеграциями с редакторами). Его код выхода и JSON-вывод являются стабильным контрактом.
### Коды выхода
`skillspector scan` завершается со следующими кодами:
| Код | Значение |
|------|---------|
| `0` | Сканирование завершено, `risk_score` ≤ 50 (рекомендация `SAFE` или `CAUTION`) |
| `1` | Сканирование завершено, `risk_score` > 50 (рекомендация `DO_NOT_INSTALL`) |
| `2` | Ошибка (неверный ввод, нечитаемый источник, внутренний сбой) |
> Код выхода объединяет `SAFE` и `CAUTION` в `0`. Чтобы действовать по-разному в отношении них (например, *предупреждать* при `CAUTION`, но *блокировать* при `DO_NOT_INSTALL`), читайте поле `recommendation` из JSON-вывода, а не полагайтесь на код выхода.
### Машиночитаемый вывод
`--format json` создаёт JSON-отчёт; без `--output`/`-o` он записывается в stdout:```bash
skillspector scan ./my-skill/ --format json
The top-level shape is (this example shows a full LLM-backed scan; with --no-llm, metadata.llm_requested is false):```json
{
"skill": { "name": "...", "source": "...", "scanned_at": "<ISO 8601>" },
"risk_assessment": { "score": 0, "severity": "LOW", "recommendation": "SAFE" },
"components": [ { "path": "...", "type": "...", "lines": 0, "executable": false, "size_bytes": 0 } ],
"issues": [ { "id": "...", "category": "...", "severity": "...", "confidence": 0.0, "location": { "file": "...", "start_line": 0 } } ],
"metadata": {
"has_executable_scripts": false,
"skillspector_version": "...",
"llm_requested": true,
"llm_available": true,
"inference_usage": [
{
"node": "semantic_security_discovery",
"request_kind": "structured_output",
"provider": "nv_inference",
"model": "azure/anthropic/claude-opus-4-6",
"model_source": "provider_response",
"usage_source": "provider_response",
"prompt_tokens": 1000,
"completion_tokens": 100,
"cached_tokens": 400,
"cache_write_tokens": 50,
"total_tokens": 1100
}
]
}
}
- `risk_assessment.severity` ∈ `LOW | MEDIUM | HIGH | CRITICAL`.
- `risk_assessment.recommendation` ∈ `SAFE | CAUTION | DO_NOT_INSTALL`, сопоставляется с severity: `LOW → SAFE`, `MEDIUM → CAUTION`, `HIGH`/`CRITICAL → DO_NOT_INSTALL`.
- `metadata.llm_error` появляется только тогда, когда анализ LLM был запрошен, но недоступен.
- `metadata.inference_usage` содержит одну очищенную запись на каждый ответ LLM, когда
провайдер предоставляет счётчики токенов. Это пустой список, когда использование недоступно;
SkillSpector никогда не оценивает недостающие токены. Итоги по промптам включают чтение и запись
кэша, чтобы последующий расчёт цен мог безопасно разделить эти категории.
`model_source` отличает независимо идентифицированную модель провайдера от
точной запрошенной модели, используемой, когда идентичность ответа отсутствует или неоднозначна.
SkillSpector в настоящее время не отправляет элементы управления кэшем промптов Anthropic, поэтому
его запросы на сканирование не могут выбирать отдельные уровни записи в кэш на 5 минут или 1 час;
поля ответа, зависящие от TTL, нормализуются защитно в агрегированный
счётчик записи в кэш.
- Полную информацию о происхождении, учёте кэша, конфиденциальности, приёме с отказом при сбое и
контракте последующего расчёта цен см. в [Телеметрия использования выводов](https://github.com/nvidia/skillspector/blob/main/docs/INFERENCE_USAGE.md).
- Полная форма каждой проблемы определена в `Finding.to_dict()` в [models.py](https://github.com/nvidia/skillspector/blob/main/src/skillspector/models.py); полагайтесь на поля выше и рассматривайте любые дополнительные поля как наилучшие усилия.
Для CI/IDE-инструментов `--format sarif` выводит SARIF 2.1.0.
### Рекомендуемое сопоставление шлюзов
При использовании SkillSpector в качестве шлюза установки сопоставьте рекомендацию с действием:
| `recommendation` | Предлагаемое действие |
|------------------|------------------|
| `SAFE` | разрешить |
| `CAUTION` | запросить / предупредить пользователя |
| `DO_NOT_INSTALL` | заблокировать |
SkillSpector вычисляет диапазон оценки и рекомендацию; насколько строгим является шлюз (например, блокирует ли `CAUTION` в CI) — это политическое решение для интегрирующего инструмента.
## Разработка
### Настройка
Все цели `make` предполагают, что виртуальное окружение уже создано и активировано. Makefile использует **uv**, если он доступен, иначе **pip**.```bash
# Clone, create venv, activate, install dev dependencies
git clone https://github.com/NVIDIA/skillspector.git
cd skillspector
uv venv .venv && source .venv/bin/activate
# or: python3 -m venv .venv && source .venv/bin/activate
make install-dev
# Run tests
make test
# Run tests with coverage
make test-cov
# Run linting
make lint
# Format code
make format
SkillSpector использует двухэтапный конвейер обнаружения:
Действительная подпись OpenSSF Model Signing корневого уровня (skill.oms.sig) сохраняется в
инвентаре компонентов как тип oms_signature, но исключается из статического и LLM-анализа содержимого.
Пакеты OMS по необходимости содержат длинные поля полезной нагрузки, подписи и сертификата в кодировке base64;
общие проверки обфусцированного кода в противном случае могут ошибочно классифицировать эти поля как скрытое исполняемое содержимое.
Распознаватель проверяет минимальную структуру OMS DSSE/in-toto; он не проверяет подпись,
цепочку сертификатов, запись в журнале прозрачности или личность подписанта. Недопустимые или нераспознанные файлы
подписей сканируются обычным образом.
Промпт LLM включает защиту от джейлбрейка, чтобы предотвратить манипулирование анализом со стороны вредоносных навыков.
SC4 использует API OSV.dev для проверки зависимостей по полной базе данных Open Source Vulnerabilities — охватывающей десятки тысяч бюллетеней по PyPI и npm.
Инструменту требуется исходящий HTTPS-доступ к api.osv.dev для получения актуальных данных об уязвимостях. Когда он недоступен, результаты ограничиваются статическим резервным списком.
SkillSpector — это эшелонированная защита, а не песочница. Прежде чем полагаться на него, знайте, что он делает и чего не делает:
SKILLSPECTOR_PROVIDER. Распознанные файлы подписей OMS исключаются. Используйте --no-llm, чтобы содержимое оставалось локальным (только статический анализ).--no-llm. Она отправляет координаты зависимостей (не содержимое файлов), не требует API-ключа и возвращается к встроенному списку, когда OSV.dev недоступен.api.osv.dev SC4 использует небольшой статический резервный списокОсновано на исследовании «Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale» (Liu et al., 2026):
from skillspector import graph
result = graph.invoke({ "input_path": "/path/to/skill", "output_format": "json", # terminal, json, markdown, or sarif "use_llm": True, # False for static-only analysis })
print(f"Risk Score: {result['risk_score']}/100") print(f"Severity: {result['risk_severity']}") print(f"Recommendation: {result['risk_recommendation']}")
for finding in result["filtered_findings"]: print(f"[{finding['severity']}] {finding['rule_id']}: {finding['message']}")
## Лицензия
Apache License 2.0 — подробности см. в [LICENSE](https://github.com/nvidia/skillspector/blob/main/LICENSE).
## Участие в разработке
Вклад приветствуется! Пожалуйста, ознакомьтесь с нашими рекомендациями по участию и отправляйте pull request'ы.
## Поддержка
- **Проблемы**: [GitHub Issues](https://github.com/NVIDIA/skillspector/issues)
| Необязательная |
SKILLSPECTOR_SEED | Необязательное целочисленное зерно выборки для провайдеров, совместимых с OpenAI, и Azure OpenAI. Другие хостируемые провайдеры и CLI-провайдеры его не получают. Поддержка остаётся зависимой от модели. | Необязательная |
ANTHROPIC_API_KEY | Учётные данные для провайдера Anthropic (SKILLSPECTOR_PROVIDER=anthropic). | Обязательна для LLM-анализа, когда SKILLSPECTOR_PROVIDER=anthropic |
ANTHROPIC_BASE_URL | Переопределяет собственную конечную точку Anthropic (по умолчанию: https://api.anthropic.com). | Необязательная |
ANTHROPIC_PROXY_ENDPOINT_URL | Полный URL конечной точки для прокси-провайдера Anthropic (raw-predict в стиле Vertex). | Обязательна, когда SKILLSPECTOR_PROVIDER=anthropic_proxy |
ANTHROPIC_PROXY_API_KEY | Bearer-токен для прокси-провайдера Anthropic. | Обязателен, когда SKILLSPECTOR_PROVIDER=anthropic_proxy |
ANTHROPIC_PROXY_API_VERSION | Значение anthropic_version, отправляемое в теле запроса (по умолчанию: vertex-2023-10-16). | Необязательная |
AWS_PROFILE | Именованный профиль AWS для провайдера Bedrock — аутентификация через SigV4 с помощью boto3. Если не задан, используется стандартная цепочка учётных данных boto3 (переменные окружения, метаданные экземпляра, SSO и т. д.). | Необязательная (используется, когда SKILLSPECTOR_PROVIDER=bedrock) |
AWS_REGION | Регион AWS для конечной точки Bedrock Runtime. По умолчанию — us-west-2. | Необязательная (используется, когда SKILLSPECTOR_PROVIDER=bedrock) |
SKILLSPECTOR_MODEL | Переопределяет модель активного провайдера. Для хостируемых провайдеров заменяет встроенное значение по умолчанию из таблицы LLM-анализа. Для claude_cli и codex_cli передаётся как --model вместо использования резервной модели локальной CLI-среды выполнения. | Необязательная |
SKILLSPECTOR_MODEL_REGISTRY | Переопределяет встроенный YAML-реестр для каждого провайдера (src/skillspector/providers/<provider>/model_registry.yaml) пользовательским путём. | Необязательная |
SKILLSPECTOR_LOG_LEVEL | Уровень журналирования: DEBUG, INFO, WARNING, ERROR (по умолчанию: WARNING). | Необязательная |