РАЗБОР
Разбор
SkyForge 1.1.1: пакетный менеджер, whitelist, blacklist и кнопка «Посмеяться» — сделано за 3 часа
Режим чтения
[ обложка статьи ]
Контекст
Неделю назад появился независимый аудит SkyForge — русскоязычного языка программирования, который я пишу. Аудит нашёл 30+ проблем, из них 5 критичных: path traversal в статике, XSS в шаблонах, дефолтный session secret, отсутствие auth на генерируемых CRUD-маршрутах, SSRF в HTTP-клиенте.
Я закрыл всё критичное за 2 часа, выпустил 1.0.8 и написал об этом пост. Но остался вопрос: а что делать, когда кто-то напишет вредоносный пакет для языка? На тот момент системы пакетов вообще не было — только библиотеки в stdlib.
Сегодня, за 3 часа, я спроектировал и выпустил систему пакетов целиком. Реестр на GitHub, whitelist доверенных, blacklist вредоносных, dry-run, show-code, verify, кнопка «Посмеяться» для забаненных пакетов. Ниже — как это работает и почему именно так.
Как работает реестр: GitHub вместо сервера
Не хотел поднимать собственный сервер пакетов — это дорого, требует хостинга и уязвимо для атак. Вместо этого решил использовать GitHub как реестр:
GET https://api.github.com/search/repositories?q=topic:skyforge-package
Кэш — 1 час в ~/.skyforge/cache/github.json. Без токена GitHub даёт 60 запросов в час, нам хватает с головой.
Что даёт:
Файл package.skf — манифест на самом языке
Манифест написан на самом SkyForge — это принципиально:
пакет {
имя = "weather"
версия = "1.0.0"
автор = "SkyMonder"
описание = "Погода из open-meteo.com"
репозиторий = "github.com/skymonder/skyforge-weather"
точка_входа = "code/weather.skf"
теги = ["погода", "api", "http"]
лицензия = "MIT"
}
Парсер манифеста — отдельный, не использует лексер SkyForge. Потому что манифест — это метаданные, он не должен меняться при эволюции синтаксиса языка. Простой regex + самописный парсер значений.
Whitelist: доверенные пакеты от автора
Проблема: если любой может опубликовать пакет, как пользователь поймёт, что weather — настоящий пакет от skymonder, а не подделка от злоумышленника?
Решение — whitelist на сервере документации. Файл trusted.json:
{
"version": 1,
"trusted": [
{
"name": "hello",
"repo": "skytech-alt/skyforge-hello",
"author": "SkyMonder",
"note": "Официальный демо-пакет"
}
]
}
Клиент при установке сверяет имя И repo. Если злоумышленник создаст репо skyforge-hello с манифестом имя = "hello", но репо будет villain/skyforge-hello — не совпадёт, пакет не пройдёт как «проверенный». Пользователь увидит жёлтый флаг «Сообщество».
Blacklist: banned.json
Обратная сторона whitelist — список вредоносных пакетов. Файл banned.json на том же сервере:
{
"version": 1,
"banned": [
{
"name": "evil-pkg",
"repo": "example/skyforge-evil-pkg",
"reason": "Кража переменных окружения через HTTP",
"banned_at": "2026-09-13",
"note": "При импорте отправлял os.environ на сторонний сервер"
}
]
}
Если пакет забанен — установка блокируется до скачивания. Проверка идёт в трёх местах:
Особенность: если сервер с banned.json недоступен, клиент использует кэш. Если и кэша нет — fail-open (пропускает установку). Это сознательный выбор: лучше пропустить вредоносный пакет в редком сценарии, чем сломать всем установку при падении сервера.
Кнопка «Посмеяться»
Это, пожалуй, самая необычная часть релиза.
Когда пакет забанен — на его странице в каталоге появляется красный блок с причиной бана и большая кнопка:
ПОСМЕЯТЬСЯ
При нажатии:
Зачем это? Публичное осмеяние — недооценённый инструмент. Автору вредоносного пакета не «запретят» — его высмеют. Технически это просто счётчик кликов, психологически — мощнее, чем красный флаг «banned». Плюс это даёт пользователям возможность «проголосовать ногами» против плохих пакетов.
Реализация: три строки JS для звука, один маршрут на стороне SkyForge для счётчика. Работает.
Безопасность установки: dry-run, show-code, verify
Три команды, которые делают установку осознанной:
1. --dry-run — показать, что будет установлено:
$ SkyForge install weather --dry-run
DRY-RUN: ничего не установлено. Что будет установлено:
Имя: weather
Версия: 1.0.0
Автор: SkyMonder
Репо: skymonder/skyforge-weather (12 зв.)
Файлов .skf: 4
Размер кода: 3421 байт
Статус: ПРОВЕРЕННЫЙ (в whitelist)
Файлы:
package.skf (280 байт)
code/weather.skf (2841 байт)
...
2. --show-code — скачать и показать код до установки:
$ SkyForge install weather --show-code
Скачиваю weather для просмотра (без установки)...
// === code/weather.skf ===
функция получить_температуру(город) {
...
}
Параноик может прочитать код, потом поставить.
3. SkyForge verify <имя> — проверка целостности после установки:
$ SkyForge verify hello
[OK] Файлы не изменялись с момента установки.
Хеш: sha256:425845ef9f715bce...
При установке считается SHA-256 всех файлов пакета. Если кто-то (или что-то) изменит файлы после установки — verify покажет [WARN] файлы изменены. А SkyForge list автоматически помечает такие пакеты ИЗМЕНЁН!.
Это защита от:
Почему за 3 часа, а не за 3 недели
Обычно системы пакетов делают месяцами. PyPI, npm, cargo — это годы работы и целые команды. У меня получилось быстро, потому что:
Не буду делать вид, что это было легко. Было много итераций: первую версию banned-проверки я сломал, тесты падали на Windows из-за cp1251, mp3 не отдавался через catch-all маршрут. Но всё это уложилось в один день.
Что не вошло в 1.1.1
Что стоит попробовать
pip install skyforge-lang==1.1.1
SkyForge search # список пакетов
SkyForge install hello --trust # поставить демо
SkyForge install hello --dry-run # preview без установки
SkyForge install hello --show-code # прочитать код
SkyForge verify hello # проверить хеши
В реестре пока один пакет (hello), но система готова к любым.
Ссылки
Вопрос
Кто-нибудь строил пакетный реестр поверх GitHub? Какие подводные камни вылезли?
Как вы решаете проблему «автор подменил содержимое репо после публикации»? У меня только хеши файлов и whitelist, этого достаточно?
Стоит ли делать собственный сервер пакетов в 1.2, или GitHub как backend — нормальная долгосрочная стратегия?
И если у кого-то есть идея, что ещё стоит забанить через banned.json для демонстрации системы — пишите. Кнопка «Посмеяться» ждёт.
Неделю назад появился независимый аудит SkyForge — русскоязычного языка программирования, который я пишу. Аудит нашёл 30+ проблем, из них 5 критичных: path traversal в статике, XSS в шаблонах, дефолтный session secret, отсутствие auth на генерируемых CRUD-маршрутах, SSRF в HTTP-клиенте.
Я закрыл всё критичное за 2 часа, выпустил 1.0.8 и написал об этом пост. Но остался вопрос: а что делать, когда кто-то напишет вредоносный пакет для языка? На тот момент системы пакетов вообще не было — только библиотеки в stdlib.
Сегодня, за 3 часа, я спроектировал и выпустил систему пакетов целиком. Реестр на GitHub, whitelist доверенных, blacklist вредоносных, dry-run, show-code, verify, кнопка «Посмеяться» для забаненных пакетов. Ниже — как это работает и почему именно так.
Как работает реестр: GitHub вместо сервера
Не хотел поднимать собственный сервер пакетов — это дорого, требует хостинга и уязвимо для атак. Вместо этого решил использовать GitHub как реестр:
- Автор создаёт публичный репозиторий с файлом package.skf в корне
- Добавляет топик skyforge-package в настройках репо
- Через 1–2 минуты пакет появляется в каталоге
GET https://api.github.com/search/repositories?q=topic:skyforge-package
Кэш — 1 час в ~/.skyforge/cache/github.json. Без токена GitHub даёт 60 запросов в час, нам хватает с головой.
Что даёт:
- Zero-хостинг: я плачу только за сервер документации на Render (бесплатный план)
- Zero-модерации: любой может опубликовать пакет, без approval
- Zero-регистрации: не нужен аккаунт в «реестре SkyForge», достаточно GitHub
- Прозрачность: репо публичное, код видно до установки
- Нельзя отозвать пакет (можно только забанить через свой blacklist)
- Нельзя контролировать версии (берётся default branch репо)
- GitHub может упасть — тогда реестр недоступен, но кэш спасает
Файл package.skf — манифест на самом языке
Манифест написан на самом SkyForge — это принципиально:
пакет {
имя = "weather"
версия = "1.0.0"
автор = "SkyMonder"
описание = "Погода из open-meteo.com"
репозиторий = "github.com/skymonder/skyforge-weather"
точка_входа = "code/weather.skf"
теги = ["погода", "api", "http"]
лицензия = "MIT"
}
Парсер манифеста — отдельный, не использует лексер SkyForge. Потому что манифест — это метаданные, он не должен меняться при эволюции синтаксиса языка. Простой regex + самописный парсер значений.
Whitelist: доверенные пакеты от автора
Проблема: если любой может опубликовать пакет, как пользователь поймёт, что weather — настоящий пакет от skymonder, а не подделка от злоумышленника?
Решение — whitelist на сервере документации. Файл trusted.json:
{
"version": 1,
"trusted": [
{
"name": "hello",
"repo": "skytech-alt/skyforge-hello",
"author": "SkyMonder",
"note": "Официальный демо-пакет"
}
]
}
Клиент при установке сверяет имя И repo. Если злоумышленник создаст репо skyforge-hello с манифестом имя = "hello", но репо будет villain/skyforge-hello — не совпадёт, пакет не пройдёт как «проверенный». Пользователь увидит жёлтый флаг «Сообщество».
Blacklist: banned.json
Обратная сторона whitelist — список вредоносных пакетов. Файл banned.json на том же сервере:
{
"version": 1,
"banned": [
{
"name": "evil-pkg",
"repo": "example/skyforge-evil-pkg",
"reason": "Кража переменных окружения через HTTP",
"banned_at": "2026-09-13",
"note": "При импорте отправлял os.environ на сторонний сервер"
}
]
}
Если пакет забанен — установка блокируется до скачивания. Проверка идёт в трёх местах:
- installer.py — при установке по имени из реестра
- cli.py — при установке локального пакета (проверка по манифесту)
- cmd_search — забаненные показываются с пометкой [BAN]
Особенность: если сервер с banned.json недоступен, клиент использует кэш. Если и кэша нет — fail-open (пропускает установку). Это сознательный выбор: лучше пропустить вредоносный пакет в редком сценарии, чем сломать всем установку при падении сервера.
Кнопка «Посмеяться»
Это, пожалуй, самая необычная часть релиза.
Когда пакет забанен — на его странице в каталоге появляется красный блок с причиной бана и большая кнопка:
При нажатии:
- Играет mp3 со злодейским смехом (<audio> элемент, 115 КБ файл)
- Счётчик увеличивается на 1
- POST на /api/посмеяться/<имя> — инкремент в памяти сервера
Зачем это? Публичное осмеяние — недооценённый инструмент. Автору вредоносного пакета не «запретят» — его высмеют. Технически это просто счётчик кликов, психологически — мощнее, чем красный флаг «banned». Плюс это даёт пользователям возможность «проголосовать ногами» против плохих пакетов.
Реализация: три строки JS для звука, один маршрут на стороне SkyForge для счётчика. Работает.
Безопасность установки: dry-run, show-code, verify
Три команды, которые делают установку осознанной:
1. --dry-run — показать, что будет установлено:
$ SkyForge install weather --dry-run
DRY-RUN: ничего не установлено. Что будет установлено:
Имя: weather
Версия: 1.0.0
Автор: SkyMonder
Репо: skymonder/skyforge-weather (12 зв.)
Файлов .skf: 4
Размер кода: 3421 байт
Статус: ПРОВЕРЕННЫЙ (в whitelist)
Файлы:
package.skf (280 байт)
code/weather.skf (2841 байт)
...
2. --show-code — скачать и показать код до установки:
$ SkyForge install weather --show-code
Скачиваю weather для просмотра (без установки)...
// === code/weather.skf ===
функция получить_температуру(город) {
...
}
Параноик может прочитать код, потом поставить.
3. SkyForge verify <имя> — проверка целостности после установки:
$ SkyForge verify hello
[OK] Файлы не изменялись с момента установки.
Хеш: sha256:425845ef9f715bce...
При установке считается SHA-256 всех файлов пакета. Если кто-то (или что-то) изменит файлы после установки — verify покажет [WARN] файлы изменены. А SkyForge list автоматически помечает такие пакеты ИЗМЕНЁН!.
Это защита от:
- supply chain атак (автор подменил содержимое репо после публикации)
- локальных модификаций (что-то в системе писало в файлы пакета)
- случайных правок
Почему за 3 часа, а не за 3 недели
Обычно системы пакетов делают месяцами. PyPI, npm, cargo — это годы работы и целые команды. У меня получилось быстро, потому что:
- Язык уже был готов — лексер, парсер, интерпретатор, веб-фреймворк. Оставалось только добавить логику поверх.
- GitHub API решает половину задач — не нужен свой сервер, своя база, своя аутентификация. Один HTTP-запрос — и у тебя список пакетов.
- Я не изобретаю архитектуру — беру то, что уже работает в экосистеме Python: манифест как package.skf, SHA-256 хеши как в pip, dry-run как в apt, whitelist/blacklist как в apt sources.
- Аудит задал правильные вопросы — после разбора 30+ дыр в собственном коде я уже думал в категориях «а что если пользователь установит что-то плохое?». Это ускорило дизайн.
Не буду делать вид, что это было легко. Было много итераций: первую версию banned-проверки я сломал, тесты падали на Windows из-за cp1251, mp3 не отдавался через catch-all маршрут. Но всё это уложилось в один день.
Что не вошло в 1.1.1
- GPG-подписи авторов. Пока только хеши файлов. Если автор сменит содержимое репо — verify это поймает, но не поймает, если это был первый push.
- Persistent счётчик смеха. In-memory, обнуляется при рестарте.
- Автоматическое обновление пакетов. Установил --force — переустановил. Никакой семантики версий пока нет.
- Зависимости. В манифесте есть поле зависимости, но оно игнорируется. Пакет может использовать подтянуть "другой-пакет", но автоматической установки нет.
Что стоит попробовать
pip install skyforge-lang==1.1.1
SkyForge search # список пакетов
SkyForge install hello --trust # поставить демо
SkyForge install hello --dry-run # preview без установки
SkyForge install hello --show-code # прочитать код
SkyForge verify hello # проверить хеши
В реестре пока один пакет (hello), но система готова к любым.
Ссылки
- PyPI: pypi.org/project/skyforge-lang/1.1.1
- Репо: github.com/skytech-alt/SkyForge-Docs
- Документация: skyforge-docs.onrender.com
- Каталог пакетов: skyforge-docs.onrender.com/пакеты
- Инструкция: skyforge-docs.onrender.com/как-создать-пакет
Вопрос
Кто-нибудь строил пакетный реестр поверх GitHub? Какие подводные камни вылезли?
Как вы решаете проблему «автор подменил содержимое репо после публикации»? У меня только хеши файлов и whitelist, этого достаточно?
Стоит ли делать собственный сервер пакетов в 1.2, или GitHub как backend — нормальная долгосрочная стратегия?
И если у кого-то есть идея, что ещё стоит забанить через banned.json для демонстрации системы — пишите. Кнопка «Посмеяться» ждёт.
AI-выжимка
сгенерировано ИИ
Тезисы статьи скоро
Статья читается полностью. Тезисы со ссылками на разделы появятся позже.
Содержание
Codeby Academy
Практика и мастерство
От основ до продвинутого — программы для практиков Codeby.
Перейти к курсу →
Поиск в обсуждении
Карта ветки
Продолжить чтение
Следующий разбор
Computer Hack Full Hidden Control Tools Pandora HVNC User Clone interface
Ещё по теме
- Статья
Комментарии
0