Skip to content

Безопасность OpenSkills

Что вы узнаете

  • Понимание трехуровневой системы защиты OpenSkills
  • Знание принципов и методов защиты от обхода путей
  • Освоение безопасной обработки символических ссылок
  • Осознание рисков ReDoS и защитных мер при парсинге YAML

Ваша текущая проблема

Возможно, вы слышали утверждение "локальное выполнение безопаснее", но не знаете конкретных мер безопасности. Или вы беспокоитесь при установке скиллов:

  • Будут ли файлы записаны в системные каталоги?
  • Могут ли символические ссылки представлять угрозу безопасности?
  • Возможны ли уязвимости при парсинге YAML в SKILL.md?

Когда использовать

Когда вам нужно:

  • Развернуть OpenSkills в корпоративной среде
  • Провести аудит безопасности OpenSkills
  • Оценить решение по управлению скиллами с точки зрения безопасности
  • Пройти технический аудит со стороны команды безопасности

Основная идея

Дизайн безопасности OpenSkills следует трем принципам:

Трехуровневая система защиты

  1. Валидация входных данных - Проверка всех внешних входов (пути, URL, YAML)
  2. Изолированное выполнение - Обеспечение операций в ожидаемых каталогах
  3. Безопасный парсинг - Защита от уязвимостей парсера (ReDoS)

Локальное выполнение + отсутствие загрузки данных + валидация входов + изоляция путей = безопасное управление скиллами

Защита от обхода путей

Что такое атака обхода путей

Обход путей (Path Traversal) - это атака, при которой злоумышленник использует последовательности типа ../ для доступа к файлам за пределами ожидаемого каталога.

Пример: Без защиты злоумышленник может попытаться:

bash
# Попытка установки в системный каталог
openskills install malicious/skill --target ../../../etc/

# Попытка перезаписи файла конфигурации
openskills install malicious/skill --target ../../../../.ssh/

Механизм защиты OpenSkills

OpenSkills использует функцию isPathInside для проверки, что путь установки находится внутри целевого каталога.

Расположение в исходном коде: src/commands/install.ts:71-78

typescript
function isPathInside(targetPath: string, targetDir: string): boolean {
  const resolvedTargetPath = resolve(targetPath);
  const resolvedTargetDir = resolve(targetDir);
  const resolvedTargetDirWithSep = resolvedTargetDir.endsWith(sep)
    ? resolvedTargetDir
    : resolvedTargetDir + sep;
  return resolvedTargetPath.startsWith(resolvedTargetDirWithSep);
}

Принцип работы:

  1. Использование resolve() для преобразования всех относительных путей в абсолютные
  2. Нормализация целевого каталога, обеспечение завершения разделителем путей
  3. Проверка, начинается ли целевой путь с целевого каталога

Проверка при установке (src/commands/install.ts:257-260):

typescript
if (!isPathInside(targetPath, targetDir)) {
  console.error(chalk.red('Security error: Installation path outside target directory'));
  process.exit(1);
}

Проверка эффективности защиты

Сценарий теста: Попытка атаки обхода путей

bash
# Нормальная установка (успешно)
openskills install anthropics/skills

# Попытка использования ../ (неудачно)
openskills install malicious/skill --target ../../../etc/
# Security error: Installation path outside target directory

Что вы должны увидеть: Любая попытка установки за пределами целевого каталога будет отклонена с отображением ошибки безопасности.

Безопасность символических ссылок

Риски символических ссылок

Символическая ссылка (Symlink) - это ярлык, указывающий на другой файл или каталог. При неправильной обработке это может привести к:

  1. Утечке информации - Злоумышленник создает символическую ссылку на конфиденциальный файл
  2. Перезаписи файлов - Символическая ссылка указывает на системный файл, который перезаписывается операцией установки
  3. Циклическим ссылкам - Символическая ссылка указывает на себя, вызывая бесконечную рекурсию

Разыменование при установке

OpenSkills использует dereference: true при копировании файлов для разыменования символических ссылок, напрямую копируя целевой файл.

Расположение в исходном коде: src/commands/install.ts:262

typescript
cpSync(skillDir, targetPath, { recursive: true, dereference: true });

Эффект:

  • Символические ссылки заменяются фактическими файлами
  • Сама символическая ссылка не копируется
  • Избегает перезаписи файлов, на которые указывают символические ссылки

Проверка символических ссылок при поиске скиллов

OpenSkills поддерживает скиллы в виде символических ссылок, но проверяет их на повреждение.

Расположение в исходном коде: src/utils/skills.ts:10-25

typescript
function isDirectoryOrSymlinkToDirectory(entry: Dirent, parentDir: string): boolean {
  if (entry.isDirectory()) {
    return true;
  }
  if (entry.isSymbolicLink()) {
    try {
      const fullPath = join(parentDir, entry.name);
      const stats = statSync(fullPath); // statSync follows symlinks
      return stats.isDirectory();
    } catch {
      // Broken symlink or permission error
      return false;
    }
  }
  return false;
}

Характеристики безопасности:

  • Использование statSync() для следования за символическими ссылками и проверки цели
  • Поврежденные символические ссылки пропускаются (блок catch)
  • Не вызывает сбоя, тихая обработка

Сценарии использования

Поддержка символических ссылок позволяет вам:

  • Использовать скиллы напрямую из git-репозитория (без копирования)
  • Синхронизировать изменения при локальной разработке
  • Делиться библиотекой скиллов между проектами

Безопасность парсинга YAML

Риск ReDoS

Отказ регулярных выражений (ReDoS) - это когда злонамеренно созданный ввод вызывает экспоненциальное время сопоставления регулярных выражений, потребляя ресурсы CPU.

OpenSkills должен парсить YAML frontmatter в SKILL.md:

yaml
---
name: skill-name
description: Skill description
---

Защита с использованием нежадных регулярных выражений

OpenSkills использует нежадные регулярные выражения для предотвращения ReDoS.

Расположение в исходном коде: src/utils/yaml.ts:4

typescript
export function extractYamlField(content: string, field: string): string {
  const match = content.match(new RegExp(`^${field}:\\s*(.+?)$`, 'm'));
  return match ? match[1].trim() : '';
}

Ключевые моменты:

  • +? - это нежадный квантификатор, соответствующий кратчайшему возможному
  • ^ и $ фиксируют начало и конец строки
  • Соответствует только одной строке, избегая сложной вложенности

Неправильный пример (жадное сопоставление):

typescript
// ❌ Опасно: + будет жадно сопоставлять, может встретить взрыв обратного отслеживания
new RegExp(`^${field}:\\s*(.+)$`, 'm')

Правильный пример (нежадное сопоставление):

typescript
// ✅ Безопасно: +? нежадно, останавливается при первом символе новой строки
new RegExp(`^${field}:\\s*(.+?)$`, 'm')

Разрешения файлов и проверка источника

Наследование системных разрешений

OpenSkills не управляет разрешениями файлов, напрямую наследуя управление разрешениями операционной системы:

  • Владелец файлов совпадает с пользователем, запускающим OpenSkills
  • Разрешения каталогов следуют настройкам umask системы
  • Управление разрешениями унифицировано контролируется файловой системой

Проверка источника для частных репозиториев

При установке из частного git-репозитория OpenSkills полагается на проверку SSH-ключей git.

Расположение в исходном коде: src/commands/install.ts:167

Рекомендация

Убедитесь, что ваш SSH-ключ настроен правильно и добавлен в список авторизованных ключей git-сервера.

Безопасность локального выполнения

OpenSkills - это чисто локальный инструмент, не включающий сетевое взаимодействие (кроме клонирования git-репозиториев):

Отсутствие загрузки данных

ОперацияПоток данных
Установка скиллаGit-репозиторий → Локальный
Чтение скиллаЛокальный → Стандартный вывод
Синхронизация AGENTS.mdЛокальный → Локальный файл
Обновление скиллаGit-репозиторий → Локальный

Защита конфиденциальности

  • Все файлы скиллов хранятся локально
  • AI-агенты читают через локальную файловую систему
  • Отсутствие облачных зависимостей или сбора телеметрии

Различие с Marketplace

OpenSkills не зависит от Anthropic Marketplace, работает полностью локально.

Резюме урока

Трехуровневая система защиты OpenSkills:

Уровень безопасностиМеры защитыРасположение исходного кода
Защита от обхода путейisPathInside() проверяет, что путь находится внутри целевого каталогаinstall.ts:71-78
Безопасность символических ссылокdereference: true разыменовывает символические ссылкиinstall.ts:262
Безопасность парсинга YAMLНежадное регулярное выражение +? предотвращает ReDoSyaml.ts:4

Запомните:

  • Атаки обхода путей используют последовательности ../ для доступа к файлам за пределами ожидаемого каталога
  • Символические ссылки требуют разыменования или проверки во избежание утечки информации и перезаписи файлов
  • Парсинг YAML использует нежадные регулярные выражения для предотвращения ReDoS
  • Локальное выполнение + отсутствие загрузки данных = более высокая конфиденциальность и безопасность

Предпросмотр следующего урока

В следующем уроке мы изучим Лучшие практики.

Вы узнаете:

  • Лучшие практики настройки проекта
  • Решения по командной работе для управления скиллами
  • Советы по использованию в мульти-агентной среде
  • Распространенные ловушки и способы их избежания

Приложение: Справочник по исходному коду

Нажмите, чтобы раскрыть расположение исходного кода

Время обновления: 2026-01-24

ФункцияПуть к файлуНомер строки
Защита от обхода путейsrc/commands/install.ts71-78
Проверка пути установкиsrc/commands/install.ts257-260
Разыменование символических ссылокsrc/commands/install.ts262
Проверка пути обновленияsrc/commands/update.ts156-172
Проверка символических ссылокsrc/utils/skills.ts10-25
Безопасность парсинга YAMLsrc/utils/yaml.ts4

Ключевые функции:

  • isPathInside(targetPath, targetDir): Проверка, что целевой путь находится внутри целевого каталога (предотвращает обход путей)
  • isDirectoryOrSymlinkToDirectory(entry, parentDir): Проверяет, является ли каталог или символическая ссылка указателем на каталог
  • extractYamlField(content, field): Извлекает поля YAML с использованием нежадных регулярных выражений (предотвращает ReDoS)

Журнал изменений:

  • CHANGELOG.md:64-68 - Описание обновления безопасности v1.5.0