PunchFG to raise Niger power plant output to 700MWThe Jerusalem PostHamas used double agents, deception to fool Israel ahead of October 7 massacre, study findsRTP DesportoAlbuquerque diz que Cristiano Ronaldo não pode ser tratado como um qualquerESPNTop scenes from Rockets, Mavs trip to Macao, China, for preseason slateESPN DeportesJoya del Arsenal recibe tres récords GuinnessBollywood HungamaPrasanna Bisht starrer Bokshi release postponed to December 4 after CBFC review over witchcraft and gruesome violenceInquirer2 wounded in roadside shooting in LaoagZDF heuteAktuelle Pressemitteilungen des ZDFStraits Times SportInfantino promises further FIFA support for African footballThe South AfricanOrlando Pirates vs Mamelodi Sundowns: Road to the MTN8 finalTechCrunchGoogle releases a new local-first Granola competitorLa TerceraPor segundo año consecutivo dos listas de izquierda pasan al balotaje en las elecciones de la FEUC
The Daily Newsstand · Free, Always
Thursday, October 8, 2026

Я написал сканер уязвимостей для вайбкода и проверил им 3 800 чужих репозиториев

Translate

Сегодня Telegram-бот для продажи VPN собирается за вечер. Открываешь Cursor, пишешь «сделай бота с оплатой в Stars и панелью Marzban», и через пару часов он уже принимает деньги. Только в config.py лежит токен бота, в docker-compose.yml открыт Postgres на 0.0.0.0:5432, а в истории git остался .env, который «потом удалили».

Мне стало интересно, насколько всё плохо на самом деле. Я написал свой SAST-сканер для кода, сгенерированного ИИ, и прогнал его по 3 800 публичным репозиториям: от проектов с тремя звёздами до платформ с десятками тысяч.

Цифры коротко:

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

~3 800

Боевых Telegram-ботов (VPN, магазины, Stars)

471

Сырых находок high/critical на этих ботах в первой версии

16 378

Из них оказались настоящими утечками

~30

Правил в сканере

21

Регрессионных тестов

193

Внешних зависимостей

0

Чужих ключей, которые я проверил или использовал

0

Последняя строка самая важная, к ней я ещё вернусь. А разница между 16 378 и 30 — это, по сути, вся история проекта: как научить сканер находить настоящие дыры и молчать про всё остальное.

Что такое AigisSAST

AigisSAST — консольный сканер безопасности для кода, написанного с ИИ. Около 3 000 строк на чистом Python, без единой зависимости и без облака: код никуда не уходит.

pip install aigis-sast
aigis scan

Внутри:

  • Python разбирается по AST, а не grep’ом. Поэтому cursor.execute(f"... {user_id}") отличается от безобидной f-строки в логгере.

  • 21 правило под типичные ошибки ИИ: токены (OpenAI, Telegram, GitHub, AWS, Stripe и др.), пароли, строки подключения к базам, закоммиченный .env, SQL- и shell-инъекции, eval, pickle, JWT без проверки подписи, CORS *, debug=True, verify=False, токены через random, FastAPI-ручки без авторизации, XSS, секреты в VITE_*/NEXT_PUBLIC_*, root в Docker, открытые порты баз.

  • Каждая находка объясняется по-человечески: чем опасно, как исправить, готовый код.

  • Секреты маскируются (7312************), чтобы ключ не утёк второй раз через логи CI.

  • Русский и английский: язык берётся из системы, переключается через --lang en.

▌ bot/config.py
   CRITICAL  AIG001  Токен или API-ключ прямо в коде (Telegram bot token)
           bot/config.py:12
           ↗ https://github.com/you/bot/blob/3f2c1ab.../bot/config.py#L12
           │ BOT_TOKEN = "7312************"
           чем опасно:
             Любой, кто увидит репозиторий, получит доступ к твоему боту...
           как исправить:
             Отзови токен у @BotFather прямо сейчас и вынеси его в .env...
────────────────────────────────────────────────────────────────
  ■ critical 1  ■ high 3  □ medium 0  ■ low 2
  оценка безопасности: 43/100   уровень  D
  начни с: AIG001 bot/config.py:12

У каждой находки есть кликабельная ссылка на файл и строку на GitHub, GitLab или Bitbucket, так что до нужного места один клик.

Он ещё и чинит

aigis fix --dry-run   # показать diff
aigis fix             # применить

Выносит ключи в .env и .env.example, дописывает .env в .gitignore, меняет verify=False на True, yaml.load на safe_load, random на secrets для токенов, выключает debug, прячет порты баз за 127.0.0.1 и сам добавляет нужные import. SQL-инъекции и JWT автоматически не трогает: там без понимания логики приложения можно только сломать.

«Я же удалил ключ»

Самая частая история: человек заметил токен, удалил его следующим коммитом и успокоился. Но старая версия файла живёт в истории git, и её видит каждый, кто сделал git clone.

$ aigis history
  [CRITICAL] AIG001  7312************  (Telegram bot token)
      bot.py  ·  коммит 402c92b от 2026-09-14  ·  удалён, но остался в истории
      ↗ https://github.com/you/bot/commit/402c92b...

В CI подключается одной командой aigis init: находки попадают во вкладку Security → Code scanning и прямо в diff пулл-реквеста.

Раунд 1: 126 вайбкод-проектов и 2 012 «паролей»

Начал я с репозиториев с явными следами ИИ: .cursorrules, CLAUDE.md, «vibe coded», «built with Cursor/Bolt/Lovable». Медиана три звезды, обычные pet-проекты.

Первый прогон получился позорным: 2 012 захардкоженных паролей. Я сел разбирать их руками, и почти всё оказалось мусором: тестовые пароли, хеши в lock-файлах, your-key-here, ${DB_PASSWORD}, переменные вроде hashed_password и ACCESS_TOKEN_EXPIRE_MINUTES, переводы, где password значит «Пароль».

После доработки осталось 138 находок, а настоящие ключи не потерялись: каждый исправленный случай я закрепил тестом. Ручная разметка показала точность по секретам примерно 60–70%. Это честная цифра, а не маркетинговая.

Раунд 2: 49 гигантов open source

Потом я пошёл к взрослым: 49 популярных ИИ-платформ, low-code-сервисов и админок с тысячами звёзд.

Правило

Было

Стало

Все находки

3 709

1 422

AIG002 пароли

1 525

392

AIG003 URL базы с паролем

276

4

AIG021 FastAPI без авторизации

299

71

AIG001 токены известных форматов

164

28

Почти все 28 оставшихся «токенов» оказались тестовыми и примерными. Крупные проекты за секретами следят. Отсюда же вылезла проблема оценки: в огромной кодовой базе даже аккуратный проект набирает сотни находок и получает F. Пересчёт с поправкой на размер стоит у меня в планах.

Раунд 3: 2 292 маленьких проекта — боты, ИИ, VPN

Дальше были маленькие свежие проекты: Telegram-боты, ИИ-приложения, сайты, VPN-боты и панели (Marzban, 3x-ui, WireGuard, Xray). Сканировались и текущий код, и вся история git.

После ручного отсева осталось около 50 проектов с доступами, похожими на настоящие: ключ Google service account вместе с .env, пароли от облачных MongoDB и TiDB, закоммиченные .env у VPN-ботов, десятки токенов ботов прямо в коде, OpenAI- и Google-ключи.

Раунд 4: 471 бот, который приносит деньги

Учебные проекты мне были уже неинтересны. Я искал ботов, которыми реально пользуются: VPN-магазины, магазины цифровых товаров, боты с оплатой в Stars, CryptoBot и ЮKassa. Фильтр: не форк, коммиты за последний год, минимум два признака живого использования (ссылка на работающего бота, подключённая оплата, деплой, админка), никаких tutorial/template.

Шаг

Репозиториев

Кандидатов из 41 поискового запроса

1 514

Прошли фильтр «боевой бот»

473

Просканировано (код + история git)

471

Похожие на настоящие утечки после ручного разбора

31

— секрет лежит в коде прямо сейчас

10

— только в истории git

22

Что нашлось: токены ботов прямо в коде, токен CryptoBot вместе с адресом и паролем панели 3X-UI в «примере» .env, GitHub-токен в истории, дамп конфига VPN-панели с приватными ключами. И популярная open-source панель, где токен бота зашит в исходники, поэтому он уезжает каждому, кто её ставит.

Самое ценное в этом раунде было не про чужих ботов, а про мой сканер. 16 378 находок, из них настоящих около 30. Шум давали:

  • переводы в VPN-панелях: "newPassword" = "Nueva Contraseña" — это подпись к полю;

  • вендорный vue.js, где emptySlotScopeToken = "_empty_" похож на токен только по имени;

  • example-значения в OpenAPI ("password": "secret");

  • тесты, шаблоны .env.j2, тестовые PEM-ключи, postgres://postgres:postgres@localhost.

Нашёлся и настоящий баг: aigis history держал весь git log -p в памяти, падал по OOM на больших историях и при этом молча писал пустой отчёт с кодом 0. Для сканера безопасности хуже бага не придумаешь: семь репозиториев чуть не записались в «чистые».

Я исправил всё. История теперь читается потоком, а при сбое git сканер честно падает с кодом 2. На одной популярной VPN-панели было 37 находок, стало 3, на другой было 29, стало 7. Настоящий зашитый токен бота при этом в отчёте остался, ради этого всё и делалось.

Раунд 5: 879 проектов вслепую

Последняя проверка самая честная: я прогнал свежую версию ещё по 879 проектам, которые сканер раньше не видел и под которые я его не подгонял. Находок снова хватило: токены ботов и API-ключи в коде и в истории git, закоммиченные .env, строки подключения к базам с паролем.

Названий проектов в статье нет ни в одном раунде, и это сделано специально.

Почему я не проверял ни одного ключа

Меня постоянно спрашивали: «Почему бы не дёрнуть getMe у Telegram и не узнать, живой ли токен?»

Потому что это уже использование чужого доступа. Запрос с чужим токеном аутентифицирует тебя как владельца бота, и неважно, что метод «только читает». Нормальный security-ресёрч устроен так: нашёл ключ по формату и контексту, сообщил владельцу файл и строку (без самого ключа), а проверку и отзыв оставил ему. Поэтому все цифры выше значат «похоже на настоящий ключ», а не «ключ работает».

Я ни разу не входил ни в один чужой сервис, бот, базу или панель и не пользовался найденными ключами. Сканер только читает публичный код и маскирует секреты. Проект я делаю для пользы сообщества: чтобы ИИ-код попадал в прод с меньшим числом дыр, а владельцы узнавали об утечках раньше злоумышленников.

Что я понял

  1. ИИ ошибается не случайно, а по шаблону. Секреты в коде, f-строки в SQL, CORS *, debug=True, ручки без Depends(...) — одни и те же ошибки в тысячах проектов.

  2. Найти легко, промолчать трудно. Больше всего времени ушло не на то, чтобы сканер находил, а на то, чтобы он не орал на всё подряд. Из 193 тестов большая часть как раз про то, чего находить не надо.

  3. Удалённый ключ — не удалённый ключ. Попал в публичный репо, значит отзывай, а не удаляй коммитом.

  4. Тихий сбой хуже ложной тревоги. Сканер, который упал и сказал «всё чисто», опаснее, чем отсутствие сканера.

Попробовать

Всё описанное выше есть в версии 0.5.0:

pip install aigis-sast
aigis help      # шпаргалка по всем командам
aigis scan      # текущий код
aigis history   # секреты в истории git
aigis fix       # автоисправление
aigis init      # подключить к GitHub Actions

Код открыт под MIT: https://github.com/jasperBLCK/AigisSAST. Если сканер ошибся на вашем проекте в любую сторону, заведите issue с примером: каждое ложное срабатывание у меня превращается в регрессионный тест.

Проект я буду развивать дальше: новые правила, меньше ложных срабатываний, поддержка других языков. Буду рад любой поддержке: звезда на GitHub, issue, PR или просто отзыв.

И вопрос к вам: насколько полезной показалась разработка и поставили бы вы её в свой CI? Напишите в комментариях, мне правда важно.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.