Appearance
Топ правил для AI-линтера (security-first)
Документ ручной: приоритизация и threat-model для репозиториев со skills, MCP, инструкциями в Markdown, tool JSON, плагинами IDE и CI-артефактами. Не заменяет сгенерированный каталог текущих кодов правил — см. SECURITY_RULES.md.
Срез: 29 марта 2026. Часть правил уже покрывается shipped SEC* в lintai-ai-security, часть — кандидаты на следующие итерации.
Актуализация для skills markdown (2026-03-29)
Смотрите обновлённую секцию ниже: ## Актуализация (2026-03-29): top-6 правил для skills markdown (самые полезные).
Полевой апдейт (2026-03-30): что выносить на первый экран
После реального прогона по 1545 файлам из official, community и stratified cohorts, лучший первый экран для сайта и docs сейчас такой:
SEC352— unscopedBashgrant в AI-native frontmatter. Увер.9/10, Надёж.9/10SEC347— mutable MCP launcher в markdown setup docs. Увер.9/10, Надёж.9/10SEC340— mutable package launcher в committed Claude hook settings. Увер.9/10, Надёж.9/10SEC329— mutable package launcher в committedmcp.json. Увер.9/10, Надёж.9/10
Почему именно так:
SEC352сейчас даёт лучший signal/noise на обычных community skills, а не только на offensive-security corpus.SEC347,SEC340иSEC329остаются самыми defendable operational rules для MCP / Claude wiring.- Эвристические и domain-sensitive правила вроде
SEC102,SEC313,SEC335,SEC348,SEC349,SEC351полезны, но хуже подходят для "первого впечатления" о качестве ruleset.
Синтез 15 исследовательских агентов (март 2026)
Был запущен параллельный ресёрч (15 подзадач) по направлениям: OWASP LLM Top 10 → статические аналоги; MITRE ATLAS mitigations → проверки в репо; официальный MCP security (в т.ч. spec 2025-11-25); Cursor / VS Code / Claude Code формы конфигов; Agent Skills spec; ENISA ETL 2025; NIST AI 600-1; GitHub Copilot custom instructions; hooks / tasks / pre-commit; небезопасная сериализация весов (HF/PyTorch guidance); CVE на MCP и AI-IDE; JSON Schema Tool (MCP); RAG chunk инварианты; plugin.json Cursor/Anthropic; SBOM / ML-BOM.
Критерий отбора «лучших» для таблиц ниже: детерминированная проверка по файлам, security-релевантность, переносимость между проектами, минимум ложных срабатываний при узкой формулировке. Отброшено: чистая эвристика «prompt injection» в prose; правила без первичного обоснования в спеке/доке.
Про два кураторских списка (волна 1 / волна 2): нумерация отражает приоритет внутри прохода куратора; между списками нет единого глобального ранга (волна 2 — CI, контейнеры, менеджеры пакетов: часто тот же класс blast radius, что пункты волны 1). Пересечения по смыслу намеренные (MCP, hooks, supply chain, ML — разные носители).
Кураторский топ-12 (лучшее из волны):
- MCP Tool по schema: обязательные
name+inputSchema($defs.Toolв официальномschema.json). - Strict function tools (OpenAI/Anthropic):
additionalProperties: false+ полнотаrequiredприstrict: true. - Литералы опасных хостов/IP в OAuth/MCP URL в репо (
169.254.169.254, внутренние диапазоны) — см. раздел SSRF в MCP security. - Отключение TLS в коде/конфигах рядом с OAuth (
verify=False,NODE_TLS_REJECT_UNAUTHORIZED=0, …). - GitHub Copilot instructions: суффикс
.instructions.md, обязательныйapplyToдля path-specific, лимит 4000 символов для code review (по докам GitHub). - Плагины: относительные пути без
.., запретhooks/mcpServers/permissionModeво frontmatter агентов внутри Claude plugin (по докам Anthropic). - Hooks / automation:
curl|bash,runOn: folderOpen+ произвольная shell-команда; закреплённыйrevв.pre-commit-config.yaml. - ML артефакты в git: политика против
.pklи небезопасных бинарных весов; приоритет Safetensors; минимальная версия PyTorch приweights_only(GHSA-53q9-r3pm-6pq6). - SBOM:
cyclonedx validate+ элементы NTIA minimum для репо с моделями (ML-BOM narrative). - OWASP LLM03/04/06 как статика: lockfile, манифест датасета с хэшами, непустой allowlist tools (политика репо).
- MITRE AML.M0033 / M0028: схема tool specs + least-privilege в закоммиченных конфигах агента.
- CVE semver: дополнение Cursor / VS Code+Copilot где продукт фиксируется в репо (см. таблицу ниже).
Вторая волна: ещё 15 агентов (март 2026)
Темы: devcontainers / Docker devcontainer.metadata, YAML (!!python/*, merge/anchors, ключ on в GHA), SSTI-аналог (Jinja/Handlebars + промпты), npm/pnpm/Corepack/install scripts / overrides drift, Python (extra-index-url, VCS без SHA, setup.py), DVC / MLflow / W&B / HF endpoint в git, OTEL / LangSmith / Langfuse секреты и «голые» промпты в трейсах, GHA (инъекция в run:, pin SHA, token+недоверенный код, cache poisoning), .env.example / direnv, Unicode tool id / ReDoS в regex-полях конфигов, WASI / Extism manifest, Cursor (.cursorignore vs terminal/MCP, envFile), Claude Code (settings.json, hooks, bypassPermissions), vector DB compose/Helm.
Кураторский топ новых правил (из второй волны):
initializeCommanddevcontainer выполняется на хосте; Features из произвольного OCI-реестра; bind-mount~/.ssh, cloud CLI,docker.sock.- Lifecycle в
LABEL devcontainer.metadataв образе — скрытый от ревьюdevcontainer.jsonвектор. - GHA: выражения
$\{\{ inputs.* \}\}/ event прямо вrun:→ script injection; third-partyuses:не на полный SHA; сочетаниеcontents: writeс checkout кода из форка; cache общий между недоверенным и привилегированным job. - YAML: теги
!!python/object*в workflow/compose; anchors +<<рядом сpermissions/environment. - Lockfile
hasInstallScriptбез политики allowlist;dangerouslyAllowAllBuilds(pnpm);packageManagerбез integrity hash (Corepack). --extra-index-url/PIP_EXTRA_INDEX_URLна неутверждённый хост (dependency confusion); git+ без pin коммита;exec/evalвsetup.py.- Committed URL DVC remote /
MLFLOW_TRACKING_URI/WANDB_BASE_URL/HF_ENDPOINT: http или private/metadata хосты. - Экспорт телеметрии: литералы API key в YAML коллектора; LangSmith
HIDE_INPUTS=falseв prod-шаблонах при включённом tracing. - SSTI-слой:
Environment.from_string/Template(с f-string/конкатенацией из ненадёжных данных; delimiters шаблонов в закоммиченных промптах без политики variables-only /\{% raw %\}. - Tool /
operationId: ASCII-only machine id; запрет default-ignorable / ZWSP в идентификаторах (UTS #39). - ReDoS: эвристики на значениях ключей
pattern/regex/regexp(вложенные квантификаторы,(a|aa)+). - Extism:
allowed_hosts: null= произвольный исходящий HTTP; узкиеallowed_paths. - Cursor: официально terminal и MCP не уважают
.cursorignore— секреты не полагаться только на ignore; литералы вenv/headers/authиenvFileв.cursor/mcp.json. - Claude Code (committed):
permissions.defaultMode: bypassPermissions, HTTP-hook не https / внеallowedHttpHookUrls, hookcommandс absolute path без$CLAUDE_PROJECT_DIR. - Vector stack:
http://к облачному вендору; api_key литералом в Helm/values; composeports0.0.0.0для qdrant/weaviate/chroma без политики.
Актуализация (2026-03-29): top-6 правил для skills markdown (самые полезные)
Ниже — 6 правил с максимальной практической ценностью для SKILL.md, AGENTS.md, .mdc, .github/instructions, .github/copilot-instructions.md, .cursor и MCP-конфигов.
Топ-6 правил (старший ручной приоритет до полевого прогона)
| Ранг | Правило | Почему полезно | Уверенность | Надёжность |
|---|---|---|---|---|
| 1 | SEC-COPILOT-PATH-LAYOUT | Формат и расположение инструкций (.github/copilot-instructions.md, .github/instructions/*.instructions.md, applyTo), чтобы instructions реально применялись в нужном контексте. | 10/10 | 10/10 |
| 2 | SEC-COPILOT-4K | В code-review лимит 4000 символов (контроль по GitHub docs) — исключает тихое отбрасывание хвостовой логики инструкций. | 10/10 | 10/10 |
| 3 | SEC-OWASP-TOOLS | Принудительный allowlist инструментов (без tools: ["*"]) снижает excessive agency и blast radius. | 10/10 | 10/10 |
| 4 | SEC-MCP-TOOL-REQ | Наличие обязательных name и inputSchema в инструментах MCP/agent-интерфейсов предотвращает невалидный execution surface. | 10/10 | 10/10 |
| 5 | SEC-OPENAI-STRICT + SEC-OPENAI-STRICT-REQ + SEC-ANTHROPIC-STRICT | Строгая валидация аргументов tool-call блокирует неожиданную семантику и подмену параметров. | 10/10 | 9/10 |
| 6 | SEC-MCP-LAUNCH + SEC-CURSOR-MCP-ENVFILE + SEC-CURSOR-IGNORE-NOT-BOUNDARY | Реальный blast-radius контроль: запуск MCP без shell-пайпов + запрет утечки секретов через env/headers + не считаем .cursorignore security boundary. | 10/10 | 9/10 |
Уже зашипленные quality-first правила из этого трека
SEC352— AI-native markdown frontmatter grants unscoped Bash tool access- статус:
Preview - community usefulness сейчас:
9.5/10 - надёжность:
9/10 - почему важно: после последнего external validation это самый сильный skills-markdown rule по signal/noise; ловит слишком широкий shell grant в AI instruction frontmatter без расплывчатой prose-эвристики
- статус:
SEC353— GitHub Copilot instruction markdown exceeds the 4000-character guidance limit- статус:
Preview - community usefulness сейчас:
8/10 - надёжность:
9.5/10 - почему важно: привязан к официальному GitHub guidance и ловит structure-level проблему, из-за которой хвост инструкций может перестать реально работать
- статус:
SEC354— Path-specific GitHub Copilot instruction markdown is missingapplyTofrontmatter- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9.5/10 - почему важно: ловит очень понятный structural misconfiguration, из-за которого path-specific Copilot instructions могут просто не применяться как задумано
- статус:
SEC355— AI-native markdown frontmatter grants wildcard tool access- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9.5/10 - почему важно: very direct least-privilege rule для skills и shared instructions; wildcard
*слишком расширяет agency и плохо переживает community review
- статус:
SEC356— Plugin agent frontmatter setspermissionMode- статус:
Preview - community usefulness сейчас:
8/10 - надёжность:
9.5/10 - почему важно: структурно запрещает смешивать permission policy с plugin agent content; это narrow spec-aligned signal, который легко объяснить сообществу
- статус:
SEC357— Plugin agent frontmatter setshooks- статус:
Preview - community usefulness сейчас:
7.5/10 - надёжность:
9.5/10 - почему важно: не даёт прятать hook execution policy внутрь agent content; остаётся узким и spec-aligned
- статус:
SEC358— Plugin agent frontmatter setsmcpServers- статус:
Preview - community usefulness сейчас:
7.5/10 - надёжность:
9.5/10 - почему важно: отделяет plugin agent docs от client/server wiring; сообществу проще ревьюить такие boundary violations, чем широкие prose rules
- статус:
SEC359— Cursor rule frontmatteralwaysApplymust be boolean- статус:
Preview - community usefulness сейчас:
8/10 - надёжность:
9.5/10 - почему важно: ловит очень понятный contract bug в
.mdc/.cursorrules, из-за которого Cursor rules могут применяться не так, как автор ожидал
- статус:
SEC360— Cursor rule frontmatterglobsmust be a sequence of patterns- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9.5/10 - почему важно: ловит path-targeting bug в
.mdc/.cursorrules, из-за которого Cursor rule может тихо применяться не к тем файлам или не матчиться как задумано
- статус:
SEC361— Claude settings file is missing a top-level$schemareference- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9.5/10 - почему важно: даёт понятный quality contract для shared
.claude/settings.json, улучшает editor validation и делает командные Claude settings проще для ревью и поддержки
- статус:
SEC362— Claude settings permissions allowBash(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: ловит прямой overly-broad shell grant в shared Claude settings; для AI infra это более practically actionable signal, чем broad prose guidance
- статус:
SEC363— Claude settings hook command uses a home-directory path in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: ловит не-portable shared Claude hook wiring; для AI команд это понятный config smell, который легко чинится переходом на
$CLAUDE_PROJECT_DIR
- статус:
SEC364— Claude settings setpermissions.defaultModetobypassPermissionsin a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: это очень явный over-agency smell в shared Claude policy; сообществу легко объяснить, почему committed bypass default хуже, чем явные reviewed allowlists
- статус:
SEC365— Claude settings allow non-HTTPSallowedHttpHookUrlsin a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: это прямой transport-policy smell для shared Claude hook allowlist;
https://проще защищать и публично отстаивать как командный стандарт
- статус:
SEC366— Claude settings allow dangerous host literals inallowedHttpHookUrls- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: metadata/private-network hook hosts в shared config выглядят как очень понятный SSRF/exfil policy smell и хорошо объясняются сообществу
- статус:
SEC367— Claude settings permissions allowWebFetch(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: даёт очень понятный least-privilege signal для shared Claude network access; wildcard fetch grant легче всего оспорить в code review и легко сузить до reviewed endpoints
- статус:
SEC368— Claude settings hook command uses a repo-external absolute path in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: ловит team-facing Claude hook wiring, которое жёстко привязано к внешнему filesystem path; community-friendly remediation очевиден — перейти на
$CLAUDE_PROJECT_DIR
- статус:
SEC369— Claude settings permissions allowWrite(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: wildcard write grant в shared AI config сообществу объяснять проще всего; это очень явный least-privilege smell с очевидным remediation path
- статус:
SEC370— path-specific GitHub Copilot instruction markdown under.github/instructions/uses the wrong file suffix- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9.5/10 - почему важно: это очень понятный structural rule для AI tooling layout; если path-specific Copilot file не заканчивается на
.instructions.md, repo получает тихий config drift, который сложно заметить в review
- статус:
SEC371— path-specific GitHub Copilot instruction markdown has an invalidapplyToshape- статус:
Preview - community usefulness сейчас:
8/10 - надёжность:
9.5/10 - почему важно: rule хорошо объясняется сообществу как config-contract check;
applyToдолжен быть реально применимым target selector, а не пустым или malformed значением
- статус:
SEC372— Claude settings permissions allowRead(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: exact wildcard read grant в shared AI config очень легко объяснить сообществу как least-privilege smell; remediation такой же defendable, как у
Write(*), но с уклоном в data exposure
- статус:
SEC373— Claude settings permissions allowEdit(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: wildcard edit grant в shared AI config напрямую размывает safety boundary для file mutation; сообществу это объяснять почти так же просто, как
Write(*), но ещё ближе к повседневому AI coding workflow
- статус:
SEC374— Claude settings permissions allowWebSearch(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
8.5/10 - почему важно: wildcard search grant в shared AI config задаёт слишком широкую external-information surface; это понятный least-privilege signal для AI workflows, где search должен быть reviewable и scoped
- статус:
SEC375— Claude settings permissions allowGlob(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: wildcard file-discovery grant в shared AI config слишком широко раскрывает workspace surface; сообществу это легко объяснить как exact least-privilege smell без prose-эвристик
- статус:
SEC376— Claude settings permissions allowGrep(*)in a shared committed config- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
9/10 - почему важно: wildcard content-search grant в shared AI config даёт слишком широкую search surface; это хорошо воспринимается сообществом как точный least-privilege contract check
- статус:
SEC377— path-specific GitHub Copilot instruction markdown has an invalidapplyToglob pattern- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: invalid
applyToglob выглядит как обычная конфигурация, но silently ломает targeting Copilot instructions; это один из самых defendable community-facing AI config checks
- статус:
SEC378— Cursor rule frontmatter should not setglobswhenalwaysApplyistrue- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: global Cursor rule с одновременными
globsсоздаёт двусмысленный routing contract; правило structural-only и очень легко принимается сообществом как config hygiene check
- статус:
SEC379— Cursor rule frontmatter contains an unknown key- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: неизвестные ключи в
.mdcсоздают ложное ощущение поддерживаемой конфигурации; это точный и практичный contract check для shared AI rule packs
- статус:
SEC380— Cursor rule frontmatter should includedescription- статус:
Preview - community usefulness сейчас:
8.5/10 - надёжность:
8.5/10 - почему важно: правила без
descriptionтяжелее ревьюить и поддерживать в shared AI repo packs; remediation очевиден и rule хорошо воспринимается как quality contract
- статус:
SEC381— Claude settings command hook should settimeoutin a shared committed config- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: shared Claude command hooks без
timeoutсоздают очень практичный operational smell; remediation в одну строку, а rule легко защитить перед сообществом как reviewable team-policy contract
- статус:
SEC382— Claude settings should not usematcheron unsupported hook events- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9.5/10 - почему важно: это точный hook-contract check с живым real-world example; rule не спорит про политику, а ловит тихий config drift, который сообществу легко принять
- статус:
SEC383— Claude settings should setmatcheron matcher-capable hook events- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: отсутствие
matcherнаPreToolUse/PostToolUseвыглядит как безобидная мелочь, но quietly размывает scope hook policy; это точный и практичный team-config contract check
- статус:
SEC384— Claude settings permissions allow bareWebSearch- статус:
Preview - community usefulness сейчас:
9/10 - надёжность:
9/10 - почему важно: bare
WebSearch— это очень широкий network-search grant в shared AI policy; rule exact, practical и уже grounded на живых repo configs
- статус:
Минимальный релизный набор (1-й проход)
SEC-COPILOT-PATH-LAYOUTSEC-COPILOT-4KSEC-OWASP-TOOLSSEC-MCP-TOOL-REQSEC-OPENAI-STRICT+SEC-OPENAI-STRICT-REQ
Где линтовать для сообщества (top-3 по практичности, с оценками)
- Вариант A: GitHub Action required check
Уверенность:10/10
Надёжность:10/10
Почему: максимальный охват, enforce для каждого PR, единообразие для OSS-репозиториев. - Вариант B: pre-commit + локальный линт
Уверенность:9/10
Надёжность:8/10
Почему: дешёвый вход, раннее обнаружение и меньше итераций PR. - Вариант C: PR advisory bot
Уверенность:8/10
Надёжность:7/10
Почему: второй слой в проектах с legacy-репозиториями или без strict CI.
Рекомендуемый rollout
pre-commit → обязательный GitHub Action → advisory-бот (поэтапно, без перегруза команд).
Обновлённые источники 2025-2026 (критичные для этого блока)
- GitHub Copilot customization / custom instructions
- GitHub Copilot customization cheat sheet
- GitHub custom agents configuration, response customization
- GitHub Actions security (script injections, pwn requests), GitHub Security Lab
- MCP spec/security + 2025-11-25 schema, MCP security best practices
- OpenAI strict function/tool calling
- Anthropic Claude security/permissions/MCP/plugins/hooks, settings, plugins reference, hooks
- Cursor MCP / ignore limitations, ignore file
- OWASP agentic LLM Top 10 (2025/2026)
Принципы
- Security важнее совместимости: gate CI в первую очередь на угрозы (утечки, подмена инструментов, supply chain, обход контракта аргументов, SSRF-литералы, автозапуск shell).
- Высокая точность: схема, semver/CVE, байты/Unicode, URL-схема, структура JSON, числовые инварианты RAG только при явных ключах в файле.
- Широкая аудитория: OSS skills, корпоративные MCP, monorepo с агентами и Copilot instructions.
Тир S — security (рекомендуемый CI gate)
Порядок строк в таблице: не глобальный рейтинг по CVSS, а кластеры по поверхности (CVE → MCP/remote → контракт tool JSON / схема → markdown агента → снова MCP launch/vars → lockfile → локальные hooks → Copilot → supply chain: devcontainer / GHA / npm / Python → ML / observability / vector / WASM). Внутри кластера — от более узнаваемых к менее специфичным для AI-репо. Для ощущения «что важнее прямо сейчас» ориентируйтесь на кураторские списки и блок «Минимальные наборы», а не на номер строки в Tier S.
| ID | Правило | Что проверяем | Угроза | Типичные пути |
|---|---|---|---|---|
| SEC-MCP-CVE | Версии mcp-remote, @modelcontextprotocol/sdk вне известных уязвимых диапазонов | RCE / cross-client data leak | package.json, lockfiles | |
| SEC-PRODUCT-CVE | Версии Cursor / Cursor CLI / VS Code в репо или lock скане — см. таблицу CVE | Компрометация IDE/CLI | политика орг., скан установок | |
| SEC-MCP-URL | Remote MCP: https, политика по loopback / private literal | SSRF, MITM, подмена OAuth flow | mcp.json, .cursor/mcp.json, server.json | |
| SEC-MCP-SSRF-LITERAL | Литералы 169.254.169.254, metadata.google.internal, частные диапазоны в строках OAuth/MCP | SSRF / metadata abuse | JSON, .env.example, код клиента MCP | |
| SEC-MCP-TLS-BYPASS | Паттерны отключения проверки TLS рядом с HTTP-клиентами OAuth | MITM, утечка токенов | исходники, shell env в конфигах | |
| SEC-MCP-SECRETS | Литералы секретов в env / headers MCP без индирекции (${input:}, ${env:}) | Утечка в git | JSON конфигов MCP | |
| SEC-MCP-SHADOW | Дубликаты имён MCP tools в дескрипторах репозитория | Tool shadowing | JSON дескрипторы | |
| SEC-MCP-TOOL-REQ | По MCP schema: у Tool есть name и inputSchema (machine schema) | Невалидный tool → странное поведение агента | codegen, фикстуры | |
| SEC-TOOLS-COLLISION | Дубликаты function.name в OpenAI-style tools | Подмена вызова | **/tools*.json | |
| SEC-OPENAI-STRICT | При strict: true: рекурсивно additionalProperties: false в parameters | Обход контракта аргументов | tool JSON | |
| SEC-OPENAI-STRICT-REQ | При strict: true: required покрывает все properties | То же | tool JSON | |
| SEC-ANTHROPIC-STRICT | Anthropic strict + input_schema.additionalProperties: false | То же | Anthropic JSON | |
| SEC-JSONSCHEMA-META | Валидация вложенной схемы по JSON Schema 2020-12 meta-schema | Подмена/битая схема | *schema*.json | |
| SEC-MD-BIDI-ZWSP | Bidi control, ZWSP, BOM в контексте агента | Trojan Source класс, скрытый текст | SKILL.md, AGENTS.md, .cursor/rules/**/*, Copilot instructions | |
| SEC-MD-DANGEROUS-URL | Схемы javascript:, data:, vbscript: | Фишинг / рендер | *.md, *.mdc | |
| SEC-MD-PEM | PEM / private key в markdown | Утечка ключей | те же | |
| SEC-MD-PIPE-SHELL | Узкий pipe-to-shell в fenced блоках | RCE через инструкции | те же | |
| SEC-MCP-REMOTE-VARS | {var} в remote URL ↔ ключи variables в server.json | Misconfig endpoint | server.json | |
| SEC-MCP-LAUNCH | Цепочки **&& / ; / ` | **, **bash -c/sh -c`** в команде запуска MCP (высокосигнальные) | Local compromise через конфиг | JSON MCP, скрипты |
| SEC-LOCKFILE | Политика lockfile + lockfile-lint (https, allowed hosts) | Supply chain | npm/pnpm/yarn locks | |
| SEC-HOOK-AUTOEXEC | curl|wget … | sh, runOn: folderOpen + не allowlist-команда | Supply chain / открытие папки = RCE | .vscode/tasks.json, hooks | |
| SEC-PRECOMMIT-PIN | .pre-commit-config.yaml: rev не ветка/плавающий тег (политика SHA) | Подмена хука | .pre-commit-config.yaml | |
| SEC-ML-ARTIFACT | Запрет .pkl и небезопасных бинарных весов в git (политика орг.) | RCE при загрузке весов | **/*.pkl, артефакты моделей | |
| SEC-COPILOT-FM | Path-specific: суффикс .instructions.md, наличие applyTo во frontmatter | Неверная загрузка инструкций | .github/instructions/** | |
| SEC-COPILOT-4K | Для веток с Copilot code review: длина файла инструкции ≤ 4000 символов (по докам) | Тихий игнор хвоста при review | .github/**/*.md (политика) | |
| SEC-DEVCONTAINER-INIT-HOST | Непустой initializeCommand в devcontainer.json | Произвольная команда на хосте до контейнера | .devcontainer.json, .devcontainer/devcontainer.json | |
| SEC-DEVCONTAINER-FEATURE-REGISTRY | features с образами вне org-allowlist (произвольный OCI registry/namespace) | Supply-chain / RCE при сборке feature | те же | |
| SEC-DEVCONTAINER-BIND-SENSITIVE | mounts: bind source содержит .ssh, .aws, .kube, docker.sock и т.п. | Утечка хост-секретов / захват docker daemon | devcontainer, compose под devcontainer | |
| SEC-DEVCONTAINER-METADATA-LABEL | В Dockerfile в LABEL devcontainer.metadata= есть lifecycle-ключи (postCreateCommand, …) | Скрытое автовыполнение относительно json в репо | Dockerfile, *.Dockerfile | |
| SEC-YAML-PYTHON-TAG | В workflow/compose/MCP yaml встречаются теги !!python/object и аналоги | Небезопасная десериализация при «не тем» парсере | .github/workflows/**, docker-compose*.yml, mcp*.yaml | |
| SEC-GHA-RUN-INJECT-INPUT | В run: встроены $\{\{ inputs.* \}\} / github.event.* (недоверенный контекст) без вынесения в env: | Script injection | .github/workflows/** | |
| SEC-GHA-ACTION-NO-SHA | uses: owner/repo@ref для сторонних action: ref не 40-char SHA (тег/ветка/короткий SHA) | Подмена тега | workflows | |
| SEC-GHA-WRITE-UNTRUSTED-CODE | permissions с write + checkout/запуск кода с head форка / pull_request_target без изоляции | Pwn request класс | workflows | |
| SEC-GHA-CACHE-POISON | Один и тот же ключ actions/cache записывается из недоверенного workflow и читается привилегированным | Cache poisoning | workflows | |
| SEC-NPM-INSTALLSCRIPT-SURFACE | В lockfile hasInstallScript: true у пакетов без политики ignore-scripts / onlyBuiltDependencies / trustedDependencies | Install-time RCE цепочка | package-lock.json, pnpm-lock.yaml + package.json | |
| SEC-PNPM-ALLOW-ALL-BUILDS | dangerouslyAllowAllBuilds: true в pnpm config | Авто-запуск всех build-скриптов при обновлении графа | pnpm-workspace.yaml, .npmrc | |
| SEC-COREPACK-NO-HASH | packageManager без +sha… (политика воспроизводимости) | Подмена менеджера пакетов | корневой package.json | |
| SEC-PY-EXTRA-INDEX-HOST | --extra-index-url / PIP_EXTRA_INDEX_URL / tool.uv.extra-index-url → хост ∉ allowlist или http | Dependency confusion (pip, PEP 708) | requirements*.txt, pyproject.toml, CI env | |
| SEC-PY-GIT-NO-SHA | git+https://…@branch без полного SHA в зависимостях (политика) | Неповторяемый / подменяемый исходник | requirements, pyproject.toml, uv.lock | |
| SEC-ML-REMOTE-URL | DVC remote url, MLFLOW_TRACKING_URI, WANDB_BASE_URL, HF_ENDPOINT: http или private/metadata хост в committed файлах | SSRF / эксфильтрация трекинга | .dvc/config, compose, Helm, .env.example | |
| SEC-OBS-EXPORT-INLINE-SECRET | В OTEL/observability YAML литералы api_key / Authorization / DD_API_KEY / LANGSMITH_API_KEY без ${…} / secretKeyRef | Утечка ключей в git | otel-collector*.yaml, compose | |
| SEC-VECTOR-HTTP-URL | http:// в URL/env для Pinecone / Qdrant / Weaviate / Chroma (не localhost по политике) | Ключи и эмбеддинги по сети без TLS | compose, Helm, config*.yml | |
| SEC-EXTISM-HOSTS-NULL | В Extism manifest allowed_hosts: null (полный интернет) | Неконтролируемый исходящий HTTP плагина | extism.json, manifest по Extism |
Связь с текущим lintai: фактические коды SEC* — только в SECURITY_RULES.md.
Тир A — сильная гигиена (security-релевантно или смежно)
| ID | Правило | Заметка |
|---|---|---|
| SEC-SKILL-METADATA | metadata только string → string | agentskills.io/specification |
| SEC-SKILL-ALLOWED-TOOLS | allowed-tools: одна строка, токены через пробел | там же |
| SEC-MCP-INPUTSCHEMA-OBJECT | inputSchema.type === "object" (проза MCP tools) | MCP server tools |
| SEC-OAS-BUNDLE | OpenAPI 3.x по OAS 3.1 schema | spec.openapis.org |
| SEC-GHA-PWN-REQUEST | pull_request_target + checkout недоверенного ref | GitHub Security Lab |
| SEC-PLUGIN-PATH | Пути в plugin.json: относительные, без .., без absolute (Cursor submit / Anthropic) | Cursor Plugins, Anthropic plugins |
| SEC-PLUGIN-AGENT | В plugin agent нет hooks, mcpServers, permissionMode во frontmatter | Anthropic — Agents in plugins |
| SEC-OWASP-LOCK | LLM03: манифест + lock по политике | LLM03 Supply Chain |
| SEC-OWASP-TOOLS | LLM06: не "tools": "*" / пустой allowlist (политика JSON) | LLM06 Excessive Agency |
| SEC-RAG-CHUNK | При явных ключах: chunk_size > 0, chunk_overlap < chunk_size | LangChain TextSplitter, LlamaIndex SentenceSplitter — gated, medium FP без контекста ключей |
| SPEC-GHA-YAML-ON-KEY | В GHA YAML корневой ключ on: в кавычках / валидный триггер (избежать boolean on в YAML 1.1) | Workflow syntax, yaml bool |
| SPEC-YAML-MERGE-REVIEW | Наличие <<: merge в compose/workflow — флаг на ручной аудит порядка слияния | YAML merge, Compose merge |
| SEC-YAML-ANCHOR-PERMISSIONS | Anchors (&/*) + merge рядом с permissions: / env: в GHA | Скрытые capabilities при ревью |
| SEC-TPL-JINJA-IN-PROMPT | В **/prompts/**, SKILL.md, **/templates/**: delimiters \{\{/\{% без документированной политики raw / variables-only | SSTI + LLM01 indirect |
| SEC-TPL-BUILD-FROM-STRING | Template( / from_string / render_template_string с шаблоном из f-string/concat из ненадёжного источника | Классический SSTI |
| SEC-NPM-BIN-SHADOW | bin в package.json с именами node/npm/npx/… (PATH confusion) | Вредоносный shim при отключённых scripts |
| SEC-OVERRIDES-DRIFT | Есть overrides/resolutions, но lockfile не отражает ожидаемые версии (эвристика) | Ложное чувство патча CVE |
| SEC-PY-PACKAGE-ALLOWLIST | Имена пакетов после PyPA normalization ∉ org allowlist / эвристика typosquat | Slopsquatting |
| SEC-PY-SETUP-EXEC | exec/eval/compile в setup.py (узкий scope файла) | Произвольный код при установке |
| SEC-REDO-CONFIG-REGEX | Значения pattern/regex/regexp с вложенными квантификаторами / (a|aa)+ | ReDoS на длинных документах |
| SEC-TOOL-ID-ASCII | operationId / tool name: политика ASCII machine id (^[A-Za-z][A-Za-z0-9_-]*$ или house style) | Homoglyph / policy bypass |
| SEC-TOOL-ID-NO-IGNORABLE | В tool id нет ZWSP / bidi / default-ignorable (UTS #39 profile) | Разные ключи при одинаковом «виде» |
| SEC-CURSOR-IGNORE-NOT-BOUNDARY | Док/политика: не считать .cursorignore единственной защитой секретов (terminal/MCP всё ещё читают файлы) | Ложное чувство защиты |
| SEC-CURSOR-MCP-ENVFILE | В .cursor/mcp.json: envFile на богатый .env + нет review политики; литералы в env/headers вместо ${env:} | Расширение blast radius stdio MCP |
| SEC-CLAUDE-BYPASS-IN-REPO | В committed .claude/settings.json: defaultMode: bypassPermissions (project) | Избыточная agency в shared config |
| SEC-CLAUDE-HOOK-PATH | Hooks command: absolute path / ~/ без $CLAUDE_PROJECT_DIR для team scripts | Невоспроизводимость / подмена пути |
| SEC-CLAUDE-HOOK-HTTP | HTTP-hook: не https или URL вне политики allowedHttpHookUrls | MITM / неконтролируемый exfil |
| SEC-ENV-TEMPLATE-FAKE-SECRET | .env.example: значения в формате реальных секретов (entropy / AKIA… / sk_live) | Сканеры, копипаст в prod |
| SEC-DIRENV-ESCAPE-ROOT | .envrc: source/dotenv на absolute пути, /etc, $HOME, выход из корня репо | Чтение чужих секретов |
| SEC-VECTOR-COMPOSE-BIND | Compose: образы qdrant/weaviate/chroma с ports: "6333:6333" без 127.0.0.1: (политика) | Публикация БД в LAN |
| SEC-LLM-TRACE-HIDE-OFF | В prod-профиле: LANGSMITH_HIDE_INPUTS=false (и аналоги) при LANGSMITH_TRACING=true | Промпты/PII в SaaS трейсах |
| SEC-OTEL-LLM-NO-SCRUB | Коллектор с LLM-телеметрией: только batch без redact/transform процессоров (эвристика) | PII в экспортёре |
Тир B — спецификация и качество (полезно, не headline security)
| ID | Правило | Заметка |
|---|---|---|
| SPEC-SKILL | Agent Skills: поля name / description / compatibility, dirname, уникальность | Specification |
| SPEC-SERVER-JSON | server.json, $schema, remotes[].type ∈ streamable-http | sse | Registry, Remote servers |
| SPEC-MCP-CLIENT | Формы Cursor mcpServers, VS Code servers+inputs, Claude .mcp.json | Cursor MCP, VS Code, Claude Code MCP |
| SPEC-AGENTS-SIZE | Codex: лимит байт цепочки инструкций | AGENTS.md guide |
| SPEC-CURSOR-MDC | YAML frontmatter .mdc, alwaysApply boolean, globs sequence | Cursor Rules |
| SPEC-SBOM | Наличие + валидация CycloneDX / SPDX + NTIA minimum при артефактах моделей | CycloneDX ML-BOM, NTIA minimum elements |
| SPEC-CLAUDE-SETTINGS-SCHEMA | Committed .claude/settings.json содержит $schema → SchemaStore claude-code-settings | Settings |
| SPEC-EXTISM-MANIFEST | Валидация JSON манифеста Extism по upstream schema | Manifest |
| SPEC-WASI-IMPORTS | Декларированный world/capabilities согласован с фактическими импортами компонента (ручной + wasm-tools) | Component worlds, wasi-cli imports |
CVE / advisory (закрепить в semver-политике линтера)
| Компонент | Диапазон / условие | Исправление | Источник |
|---|---|---|---|
| mcp-remote (npm) | уязвимые версии по advisory | ≥ 0.1.16 | CVE-2025-6514, GHSA-6xpm-ggf7-wc3p |
| @modelcontextprotocol/sdk | 1.10.0–1.25.3 | ≥ 1.26.0 | CVE-2026-25536, GHSA-345p-7cg4-v4c7 |
| VS Code + Copilot (экосистема Microsoft) | по NVD/MSRC для CVE-2026-21518 | по MSRC | CVE-2026-21518 |
| Cursor CLI | по GHSA / NVD | по advisory | CVE-2025-61592, GHSA-v64q-396f-7m79 |
| Cursor (desktop/agent) | по GHSA / NVD | по advisory | CVE-2026-31854, GHSA-hf2x-r83r-qw5q |
Точные CPE/диапазоны меняются — в CI сверяйте NVD/MSRC на дату сборки.
Минимальные наборы
Только security gate (расширенный ~14)
- SEC-MCP-CVE (+ SEC-PRODUCT-CVE если сканируете IDE)
- SEC-MCP-URL + SEC-MCP-SSRF-LITERAL + SEC-MCP-TLS-BYPASS
- SEC-MCP-SECRETS
- SEC-MCP-SHADOW + SEC-TOOLS-COLLISION + SEC-MCP-TOOL-REQ
- SEC-OPENAI-STRICT + SEC-OPENAI-STRICT-REQ + SEC-ANTHROPIC-STRICT
- SEC-MD-BIDI-ZWSP + SEC-MD-DANGEROUS-URL + SEC-MD-PEM + SEC-MD-PIPE-SHELL
- SEC-LOCKFILE + SEC-MCP-REMOTE-VARS
- SEC-MCP-LAUNCH + SEC-HOOK-AUTOEXEC + SEC-PRECOMMIT-PIN
- SEC-COPILOT-FM + SEC-COPILOT-4K (если используете Copilot instructions в репо)
- SEC-PLUGIN-PATH + SEC-PLUGIN-AGENT (если шипятся плагины)
- SEC-ML-ARTIFACT (если в репо веса моделей)
- SEC-JSONSCHEMA-META
Расширение «monorepo + CI + devcontainer» (вторая волна)
- Devcontainer: SEC-DEVCONTAINER-INIT-HOST, SEC-DEVCONTAINER-FEATURE-REGISTRY, SEC-DEVCONTAINER-BIND-SENSITIVE, SEC-DEVCONTAINER-METADATA-LABEL
- GitHub Actions: SEC-GHA-RUN-INJECT-INPUT, SEC-GHA-ACTION-NO-SHA, SEC-GHA-WRITE-UNTRUSTED-CODE, SEC-GHA-CACHE-POISON (+ уже SEC-GHA-PWN-REQUEST)
- YAML supply chain: SEC-YAML-PYTHON-TAG, SEC-YAML-ANCHOR-PERMISSIONS
- JS/TS installs: SEC-NPM-INSTALLSCRIPT-SURFACE, SEC-PNPM-ALLOW-ALL-BUILDS, SEC-COREPACK-NO-HASH
- Python deps: SEC-PY-EXTRA-INDEX-HOST, SEC-PY-GIT-NO-SHA
- ML/vectors/observability: SEC-ML-REMOTE-URL, SEC-VECTOR-HTTP-URL, SEC-VECTOR-COMPOSE-BIND, SEC-OBS-EXPORT-INLINE-SECRET
- Плагины WASM: SEC-EXTISM-HOSTS-NULL
Security + спека
Добавить SPEC-SKILL, SPEC-SERVER-JSON, SPEC-MCP-CLIENT, SEC-OAS-BUNDLE, SEC-RAG-CHUNK (с gate по ключам), SPEC-SBOM при моделях; при Claude Code в git — SPEC-CLAUDE-SETTINGS-SCHEMA; при GHA — SPEC-GHA-YAML-ON-KEY; при Extism — SPEC-EXTISM-MANIFEST.
Ограничения статического линтера
- Семантический prompt injection в свободном prose — низкая точность как единственный gate.
- Confused deputy / token passthrough в OAuth — в основном рантайм; статика ловит только грубые литералы и антипаттерны в коде.
- RAG chunk — разные единицы (токены vs символы); линтить только с явной меткой или известным классом конфига.
Первоисточники (расширенный список)
(Плюс: Agent Skills, Registry, Cursor Rules, OpenAI function calling, Anthropic structured outputs, Codex AGENTS.md, CVE-2021-42574, TR36, OpenAPI 3.1, JSON Schema 2020-12, GitHub Actions hardening.)
См. также
- SECURITY_RULES.md — фактические коды
SEC*и shipped rules. - RULE_QUALITY_POLICY.md — политика точности и promotion.
- POSITIONING_AND_SCOPE.md — границы продукта.