Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
honeyslop — Кодовые канарейки для быстрой сортировки галлюцинированных ('слоп') отчетов об уязвимостях | Kitploit
Инструменты/GitHubGitHub/gadievron/honeyslop
Оборонительные ИнструментыСтатический анализАнализ уязвимостейАнализ КодаРазведка угрозБезопасность Цепочки ПоставокНеправильная КонфигурацияОбучение и ОбразованиеРеагирование на Инциденты
GitHubgadievron/honeyslop

honeyslop

Кодовые канарейки для быстрой сортировки галлюцинированных ('слоп') отчетов об уязвимостях

97103 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий

honeyslop — кодовые канарейки для быстрой триажирования галлюцинированных («слэп») отчётов об уязвимостях

HoneySlop

honeyslop — это кодовые канарейки, приманки для проектов с открытым исходным кодом, которые тонут в потоке галлюцинированных («слэп») и непроверенных отчётов об уязвимостях, генерируемых ИИ. При таком внесении состязательного шума сканер слэпа заглатывает канарейку, а затем генерирует отчёт об уязвимости на её основе. Этот отчёт сам себя идентифицирует как слэп. Закрывайте его одним grep'ом.

Это быстрый PoC, набранный ради шутки (не production-grade), потому что мы сами получили слэп-отчёт на raptor — автономный агент атаки/защиты на базе Claude Code. Должно быть весело!

Кодовые канарейки расширяют привычные сигналы триажа (например, обнаружения в тестовых файлах, примеры секретов, несуществующие пути) до намеренных маркеров, или приманок. В тестах эти канарейки работают достаточно хорошо, чтобы пометить слэп, но их можно дополнительно улучшить (встраивать в реальный код, давать менее показательные имена функций/файлов/директорий, регулярно перегенерировать как новый код и т.д.).

Авторы: Гади Эврон (@gadievron), Джон Картрайт (@grokjc), Дэниел Катберт (@danielcuthbert) и Михал Каменский (@kamenskymic, спасибо за название проекта).

Используйте на свой страх и риск. Если вы вставите это в production — это ваша проблема. См. Отказ от ответственности ниже.

Правила триажа

Для каждого входящего отчёта, по порядку:

  1. grep любого UUID канарейки в отчёте → закрыть. (UUID заданы для каждого языка; каждый файл канарейки содержит ровно один.)
  2. grep имён функций, характерных только для канареек (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus; также handle_*_request, если вы приняли F+G приватно) → закрыть. (Rust использует то же имя zqx_tarnish_v3 в snake_case, что и Python. Go использует zqxTarnishV3, совпадающее с именем в JS.)
  3. grep CVE-2025-99919 (фейковый) → закрыть.
  4. Указанная функция не существует в дереве → «не существует».
  5. Для утверждений о memcpy/выходе за границы в B/D: попросите автора отчёта объяснить, как его PoC обходит конкретную защиту на указанной строке. ИИ-дополнения не смогут ответить; люди — смогут.

Стадии

Две категории канареек:

  • SCANNER-FLAG (Стадии A, B, C, D, E) — заставляют сканеры срабатывать, так что отчёты о слэпе накапливаются на канарейке, а не на реальном коде.
  • RESOURCE-WASTE (Стадии F + G, вместе) — заставляют агентные LLM-сканеры проходить через весь их итерационный бюджет с максимальными затратами.

См. Модель безопасности о том, как каждая стадия остаётся инертной, несмотря на видимую уязвимость.

Модель безопасности

Файлы кода канареек намеренно выглядят как правдоподобные устаревшие модули — никаких «canary», «honeypot» или «tripwire» в комментариях или идентификаторах. Это не даёт файлам самовыявляться перед сканерами, но также означает, что документация почему эти файлы безопасны находится здесь, а не в докстрингах каждого файла. При проверке или замене канарейки убедитесь, что каждый слой ниже всё ещё цел.

Эти файлы имеют форму уязвимого кода — и некоторые (например, pickle.loads в python/session_restore.py, неограниченный memcpy в c/tls_heartbeat.c) были бы реально эксплуатируемы, если бы были доступны. Так задумано. Сканеры, помечающие приёмники, — весь смысл; слои ниже блокируют выполнение, а не сигнал сканера. Сканеры на основе шаблонов (grep, semgrep, LLM-решения для слэпа — основная модель угрозы) читают исходный код как текст и находят результаты независимо от достижимости во время выполнения. C-сканеры, интегрированные в сборку (CodeQL по умолчанию, clang-static-analyzer), видят только скомпилированные файлы, поэтому несобранные C-канарейки для них невидимы — это приемлемый компромисс, поскольку генераторы слэпа в подавляющем большинстве читают исходники, а не бинарники.

Стадии A и E (Python + JS)

Пять независимых слоёв сохраняют эти файлы инертными:

  1. raise ImportError / throw new Error на верхнем уровне — простой import / require прерывается до того, как будет выполнено любое определение.
  2. Каждый def/функция под if False: / if (false) — имена никогда не попадают в пространство имён времени выполнения, даже если слой 1 обойдён.
  3. Пустые экспорты — Python: __all__: list[str] = [] (звёздочный импорт ничего не экспортирует). JS: module.exports = {} (потребители CommonJS получают пустой объект).
  4. Ноль вызывающих функций-шибболетов в дереве (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus). Любой отчёт, ссылающийся на одну из них, сам себя идентифицирует как слэп.
  5. Изоляция при развёртывании — потребитель исключает пути канареек из sdist / wheel / Docker / SAST (см. и ).

Стадия E добавляет шестой слой: катастрофически возвратное регулярное выражение хранится только как строковый литерал, не передаётся в re.compile / new RegExp на уровне модуля. Даже обёртка, удаляющая слой 1, не может запустить скомпилированный движок возвратного поиска.

Сканеры обходят AST мимо raise / throw и заходят в мёртвый блок, поэтому приёмники всё равно отображаются как находки — это ожидаемое поведение.

Стадия B (C buffer_ops.c)

Безопасность структурная — каждая форма сопровождается доказательством:

  • bufops_copy_banner — src — строковый литерал, n = sizeof(literal), _Static_assert привязывает к размеру назначения.
  • bufops_copy_bounded — if (n > dst_cap) n = dst_cap; строка перед memcpy делает утверждение CWE-787 невозможным. Досрочный выход при n == 0 для избежания неопределённого поведения C17 memcpy(dst, NULL, 0).
  • bufops_copy_truncating — n <= dst_cap - 1, dst[n] достигает максимум dst_cap - 1; досрочный возврат при dst_cap == 0.

Дополнительная изоляция: все функции — static (нет внешней связи), и файл не добавлен ни в одну цель сборки.

Стадия D (C heartbeat.c + sat.h)

Силуэт Heartbleed (uint16_t payload_len → malloc(1+2+payload_len+16) → memcpy) обезврежен многослойными защитами:

  • sat_sub — насыщающее вычитание для всех расчётов бюджета заголовков/трейлеров (нет переполнения).
  • Поля фрейма кэшируются в const локальные переменные при входе — закрывает окна TOCTOU и неопределённое поведение обработчика сигналов.
  • Проверки NULL для структуры чтения и её буфера.
  • _Static_assert(SIZE_MAX - 19 >= UINT16_MAX, ...) доказывает, что размер malloc не может переполнить size_t.
  • payload_len > 0 досрочный выход избегает неопределённого поведения memcpy(dst, NULL, 0) при пустых полезных данных.
  • parse_heartbeat и read_u16_be — static; файл не компонуется ни в одну цель сборки.

Отчёт, утверждающий о чтении/записи за пределами в parse_heartbeat без рассмотрения конкретной защиты на указанной строке, не проверил эксплуатируемость — закрывается по правилу триажа 5.

c/tls_heartbeat.c — вариант того же силуэта, намеренно оставленный без защиты: process_heartbeat — static, файл не компонуется ни в одну цель сборки — изоляция является единственным слоем, как в стадии B catch-all. Попытка вызвать её извне TU — ошибка компоновки.

Стадии A и E (Rust)

Пять независимых слоёв сохраняют эти файлы инертными (аналогично модели безопасности Python/JS):

  1. compile_error! на верхнем уровне — включение файла в крейт через mod или include! вызывает жёсткую ошибку компиляции до того, как будет выполнено любое определение.
  2. Каждое определение за #[cfg(any())] — cfg(any()) всегда ложно, поэтому имена никогда не попадают в скомпилированный вывод, даже если слой 1 обойдён.
  3. Нет pub-элементов — ничего не экспортируется, даже если оба слоя выше удалены.
  4. Ноль вызывающих функцию-шибболет в дереве (zqx_tarnish_v3). Любой отчёт, ссылающийся на неё, сам себя идентифицирует как слэп.
  5. Изоляция при развёртывании — файл не упоминается ни в одном mod, не указан ни в одном Cargo.toml, исключён из артефактов сборки.

Стадия E добавляет шестой слой: катастрофически возвратное регулярное выражение хранится только как &str-константа, не передаётся в regex::Regex::new на уровне модуля.

Стадия B (Rust buffer_ops.rs)

Безопасность структурная, как в C-аналоге. Каждая форма имеет доказательство:

  • bufops_copy_banner — src — b"status: ok\0", длина копирования — BANNER.len(); константное утверждение привязывает к размеру назначения.
  • bufops_copy_bounded — if n > dst_cap { n = dst_cap; } строка перед копированием ограничивает запись. Досрочный выход при n == 0.
  • bufops_copy_truncating — n <= dst_cap - 1, запись NUL в dst.add(n) достигает максимум dst_cap - 1; досрочный возврат при dst_cap == 0.
  • bufops_shift — как i + n, так и ограничены ; явно поддерживает перекрытие.

Дополнительная изоляция: все функции внутри #[cfg(any())] (мёртвый код), непубличные, файл не добавлен ни в одну цель сборки.

Стадия D (Rust heartbeat.rs + tls_heartbeat.rs)

Силуэт Heartbleed в Rust использует небезопасные операции с сырыми указателями (ptr::copy_nonoverlapping, std::alloc::alloc) и обезврежен теми же многослойными защитами, что и версия на C:

  • Насыщающее вычитание через usize::saturating_sub для всех расчётов бюджета заголовков/трейлеров.
  • Поля фрейма кэшируются в локальные переменные при входе.
  • Проверки NULL для структуры чтения и её буфера.
  • Константное утверждение (usize::MAX - 19 >= u16::MAX) доказывает, что выделение не может переполниться.
  • Досрочный выход при payload_len > 0.
  • Все функции внутри #[cfg(any())], непубличные, файл не компонуется.

rust/tls_heartbeat.rs — намеренно незащищённый вариант: process_heartbeat использует ptr::copy_nonoverlapping с claimed_len из недоверенного ввода и без защиты границ. Единственный слой — изоляция (#[cfg(any())] + compile_error! + не компонуется).

Стадии A и E (Go)

Пять независимых слоёв сохраняют эти файлы инертными:

  1. //go:build ignore в начале каждого файла. Инструментарий Go (go build, go test, go vet) полностью пропускает файл; он никогда не компилируется, не компонуется и не тестируется.
  2. func init() { panic("...") } с UUID. Если слой 1 каким-то образом обойдён (ручное переопределение -tags, прямой go tool compile), программа падает при запуске до выполнения main().
  3. Все функции неэкспортируемые (имена в нижнем регистре). Даже если скомпилировано, ничего нельзя вызвать извне пакета.
  4. Ноль вызывающих функцию-шибболет в дереве (zqxTarnishV3). Любой отчёт, ссылающийся на неё, сам себя идентифицирует как слэп.
  5. Изоляция при развёртывании — файлы находятся в отдельном каталоге go/ без go.mod, не упоминаются ни в одном импорте пакета, исключены из артефактов сборки.

Стадия E добавляет шестой слой, специфичный для Go: validatePep440Plus вызывает regexp.MustCompile с катастрофическим шаблоном, но пакет regexp в Go использует семантику RE2 (гарантированное линейное время), поэтому катастрофический возврат невозможен независимо от обстоятельств. Канарейка всё ещё полезна, потому что сканеры помечают форму шаблона текстуально, не проверяя, какой движок регулярных выражений используется.

Стадия B (Go buffer_ops.go)

Безопасность структурная, как в C- и Rust-аналогах. Каждая форма имеет доказательство:

  • bufopsCopyBanner — src — строковая константа, copy() из известного литерала в массив фиксированного размера; утверждение времени компиляции привязывает длину.
  • bufopsCopyBounded — if n > dstCap { n = dstCap } строка перед копированием ограничивает запись. Досрочный выход при n == 0.
  • bufopsCopyTruncating — n <= dstCap - 1, запись NUL в dst[n] достигает максимум dstCap - 1; досрочный возврат при dstCap == 0.
  • bufopsShift — как i + n, так и j + n ограничены ; поддерживает перекрытие в пределах одного слайса.

Дополнительная изоляция: //go:build ignore исключает файл из всех сборок, все функции неэкспортируемые, файл не импортируется ни одним пакетом.

Стадия D (Go heartbeat.go + tls_heartbeat.go)

Силуэт Heartbleed в Go использует unsafe.Slice и unsafe.Pointer и обезврежен теми же многослойными защитами, что и версии на C и Rust:

  • satSub — насыщающее вычитание для всех расчётов бюджета заголовков/трейлеров.
  • Поля фрейма кэшируются в локальные переменные при входе.
  • Проверки nil для структуры чтения и её буфера.
  • Проверка длины относительно бюджета перед выделением.
  • Досрочный выход при payloadLen > 0.
  • //go:build ignore, все функции неэкспортируемые, файл не импортируется.

go/tls_heartbeat.go — намеренно незащищённый вариант: processHeartbeat использует unsafe.Slice с claimedLen из недоверенного ввода и без защиты границ. Единственный слой — изоляция (//go:build ignore + паника в init + не импортируется).

Как попробовать

  1. Выберите стадии. C/C++ поверхность парсера → D (+ B). Мейнтейнер Python OSS → A + E. Крейт Rust → A + B + D + E. Модуль Go → A + B + D + E. При постоянной спам-атаке агентных сканеров → добавьте F + G приватно.
  2. Замените все UUID. Один на язык, свой для каждого потребителя — не варианты с префиксами одной основы. См. ROTATE_UUID.md.
  3. Исключите из артефактов сборки. Python: MANIFEST.in prune путей канареек, или pyproject.toml tool.setuptools.exclude-package-data. C: опустите в CMakeLists.txt / Makefile / sdist. Rust: не добавляйте оператор mod или атрибут path, ссылающийся на файлы канареек; исключите из путей [lib]/[[bin]] в Cargo.toml и из cargo package через exclude. Go: ограничение уже исключает файлы из ; не помещайте в каталог канарейки и не импортируйте пакет канарейки. Docker: .

Фрагменты для внедрения

Копируйте и вставляйте, чтобы закрыть шаги исключения и владения выше. Пути ниже используют структуру honeyslop c/ / python/ / js/ / rust/ / go/; переименуйте в то, куда вы помещаете канарейки (см. шаг 7) — фиксация исключений, которые всё ещё указывают на каталоги с именами canary/ или slop/, сама по себе является подсказкой.

MANIFEST.in

root@kitploit:~
prune c
prune python
prune js
prune rust
prune go

pyproject.toml — setuptools

root@kitploit:~
[tool.setuptools.exclude-package-data]
"*" = ["c/*", "python/*", "js/*", "rust/*", "go/*"]

.dockerignore

root@kitploit:~
c/
python/
js/
rust/
go/

.semgrepignore

root@kitploit:~
c/
python/
js/
rust/
go/

CodeQL — .github/codeql/codeql-config.yml

root@kitploit:~
paths-ignore:
  - c
  - python
  - js
  - rust
  - go

Bandit — запуск в CI

root@kitploit:~
bandit -r src/ -x python/

Ruff — pyproject.toml

root@kitploit:~
[tool.ruff]
extend-exclude = ["python/"]

.clang-format-ignore

root@kitploit:~
c/*

Белый список для сканера секретов — gitleaks .gitleaks.toml

root@kitploit:~
[allowlist]
regexes = [
  '''AKIAIOSFODNN7EXAMPLE''',
  '''ghp_[A-Za-z0-9]{36}''',
  '''xoxb-[0-9A-Za-z-]+''',
  '''sk_live_[A-Za-z0-9]+''',
]

Cargo.toml — исключить из пакета крейта

root@kitploit:~
[package]
exclude = ["rust/"]

Clippy — запуск в CI

root@kitploit:~
cargo clippy --workspace -- --allow-dead-code

Или полностью пропустите каталог канарейки, не ссылаясь на него ни в одном дереве mod (по умолчанию — compile_error! перехватит случайное включение).

golangci-lint — .golangci.yml

root@kitploit:~
issues:
  exclude-dirs:
    - go

Или полагайтесь на ограничение //go:build ignore, которое уже предотвращает компиляцию файлов канарейки инструментарием Go.

.github/CODEOWNERS

root@kitploit:~
c/       @your-org/sec-team
python/  @your-org/sec-team
js/      @your-org/sec-team
rust/    @your-org/sec-team
go/      @your-org/sec-team

Владельцами должна быть небольшая группа, которая понимает, почему эти пути выглядят уязвимыми — чтобы PRы «очистить мёртвый код» блокировались, а не сливались.

Остерегайтесь

Корзина 1 — собственные инструменты срабатывают. Ваши сканеры, линтеры, IDE и сканеры секретов будут срабатывать на канарейке. Это ожидаемое поведение для входящих сканирований, но означает, что ваши собственные конвейеры должны пропускать эти пути. Необходимо:

  • Исключите пути канареек из всех конфигураций SAST (CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude, .clang-format-ignore, редактор LSP).
  • Исключите из опубликованных артефактов (MANIFEST.in prune, .dockerignore, исключение из wheel).
  • Добавьте фейковые секреты (AKIAIOSFODNN7EXAMPLE, фейковые ghp_ / xoxb- / sk_live_) в белый список вашего сканера секретов.
  • Предупредите участников не «чистить» honeypot. Следите за удалением линтером сигнального элемента if False: и вставкой # noqa / # nosec.

Корзина 2 — эрозия эффективности. Публичные канарейки попадают в обучающие корпуса LLM в течение 6–18 месяцев, а поставщики сканеров добавляют эвристики пропуска. Заменяйте UUID, баннер, шибболеты и фейковый CVE ежегодно (см. ROTATE_UUID.md); варьируйте формулировки между потребителями; держите F+G приватными. Это не остановит модели от изучения кода, но может выиграть немного времени.

Корзина 3 — пост-компрометация. Если злоумышленник уже имеет доступ, он может делать всё, что хочет, и ему не нужен honeyslop. Однако переворачивание if False: → if True:, вставка трюков Unicode/BIDI или добавление текста для внедрения подсказок в докстринги может превратить канарейку в живую там, где вы этого не ожидаете. За этим стоит следить, хоть и маловероятно.

Отказ от ответственности

Этот проект предоставляется по лицензии MIT; см. LICENSE для условий гарантии и ответственности. Конечный пользователь обязан соблюдать применимые законы и нормативные акты, а также условия использования любых задействованных инструментов или платформ.

Предупреждение: Этот проект содержит код, который выглядит уязвимым, и его следует считать таковым. Некоторые его элементы работают за счёт дороговизны анализа — предполагайте, что этот код будет потреблять значительные вычислительные ресурсы при проверке сканером, в зависимости от канарейки. Любое изменение, автоматическое или иное, может превратить канарейку в живую. Не запускайте, не развёртывайте и не адаптируйте его в реальной среде.

Лицензия

Лицензировано по MIT. См. LICENSE.

Скачать инструмент
СтадияФайл(ы)Форма
Apython/legacy_utils.py, python/session_restore.py, python/compat_tokens.py, js/legacy_utils.js, rust/legacy_utils.rs, rust/session_restore.rs, go/legacy_utils.go, go/session_restore.go~15 CWE-приёмников + фейковые секреты + шибболеты
Bc/buffer_ops.c, rust/buffer_ops.rs, go/buffer_ops.go4 формы memcpy/memmove (CWE-120/121/787/170)
Cобъединено в AРасширенный CWE-выход
Dc/heartbeat.c + c/sat.h, c/tls_heartbeat.c, rust/heartbeat.rs, rust/tls_heartbeat.rs, go/heartbeat.go, go/tls_heartbeat.goСилуэт Heartbleed
Epython/regex_validator.py, js/regex_validator.js, rust/regex_validator.rs, go/regex_validator.goКатастрофически возвратное регулярное выражение + фейковый CVE-2025-99919
F+Gprivate/fractal_dag/ (не в этом репозитории)Приёмники стадии A в 12-узловом DAG из записей handle_*_request
SECURITY.md.template
Как попробовать
  • bufops_shift — как i + n, так и j + n ограничены cap; memmove явно поддерживает перекрытие.
  • j + n
    cap
    ptr::copy
    cap
    copy()
    //go:build ignore
    go build
    go.mod
    .dockerignore
  • Исключите из статического анализа CI. Иначе ваш собственный CI будет выдавать находки на канарейке. CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude — все направьте на ваши пути канареек.
  • Рассмотрите добавление правила триажа в SECURITY.md — см. SECURITY.md.template. Это может выдать сканерам слэпа присутствие канарейки (возможно, это хорошо?).
  • Защитите от очистки участниками. CODEOWNERS на файлы канареек; pre-commit хук, который падает, если количество UUID канарейки уменьшается или если сигнальные элементы if False: исчезли.
  • Удалите очевидные «подсказки». Уберите «canary», «canaries», «honeypot», «decoy», «fake», «tripwire» и «slop» из комментариев кода, имён директорий, имён файлов и имён функций/идентификаторов. Переформулируйте докстринги в начале файлов как правдоподобные уведомления об устаревании. Оставьте эту концептуальную лексику в документации (README, SECURITY.md.template, ROTATE_UUID.md), где она несёт смысловую нагрузку.