Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
honeyslop — Canarios de código para triar rápidamente informes de vulnerabilidad alucinados ('slop') | Kitploit
Herramientas/GitHubGitHub/gadievron/honeyslop
Herramientas DefensivasAnálisis EstáticoAnálisis de VulnerabilidadesAnálisis de CódigoInteligencia de AmenazasSeguridad de Cadena de SuministroMala ConfiguraciónAprendizaje y EducaciónRespuesta a Incidentes
GitHubgadievron/honeyslop

honeyslop

Canarios de código para triar rápidamente informes de vulnerabilidad alucinados ('slop')

9710hace 3 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio

honeyslop - canarios de código para triage rápido de reportes de vulnerabilidades alucinados ("slop")

HoneySlop

honeyslop son canarios de código, señuelos, para proyectos de código abierto que se ahogan en reportes de vulnerabilidades alucinados por IA ("slop") y no verificados. Con dicha inyección de ruido adversario, un escáner de slop ingiere el canario y luego genera un "reporte" de vulnerabilidad basado en él. El reporte se autoidentifica como slop. Ciérralo con un grep.

Esto es un PoC rápido, vibe-coded como broma (no listo para producción), porque nosotros mismos recibimos un reporte slop en raptor, un agente autónomo de ataque/defensa basado en Claude Code. ¡Debería ser divertido!

Los canarios de código extienden señales familiares de triage (p. ej., detecciones en archivos de prueba, secretos de ejemplo, rutas inexistentes) hacia marcadores deliberados, o señuelos. En pruebas, estos canarios funcionan lo suficientemente bien para marcar slop, pero pueden mejorarse aún más (incrustados en código real, nombres de funciones/archivos/directorios menos indicativos, regenerados regularmente como código nuevo, etc.).

Escrito por: Gadi Evron (@gadievron), John Cartwright (@grokjc), Daniel Cuthbert (@danielcuthbert) y Michal Kamensky (@kamenskymic, con crédito por nombrar el proyecto).

Úselo bajo su propio riesgo. Si pegas esto en producción, es problema tuyo. Véase Descargo de responsabilidad más abajo.

Reglas de triage

Para cada reporte entrante, en orden:

  1. haz grep de cualquier UUID de canario en el reporte → cerrar. (Los UUIDs son por idioma; cada archivo canario incrusta exactamente uno.)
  2. haz grep de nombres de funciones solo de canario (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus; también handle_*_request si has adoptado F+G en privado) → cerrar. (Rust usa el mismo nombre snake_case zqx_tarnish_v3 que Python. Go usa zqxTarnishV3, coincidiendo con el nombre de JS.)
  3. haz grep de CVE-2025-99919 (falso) → cerrar.
  4. La función citada no existe en el árbol → "no existe".
  5. Para afirmaciones de memcpy/límites en B/D: pida al reportero que explique cómo su PoC vence la protección específica en la línea citada. Los seguimientos de IA no pueden responder; los humanos sí.

Etapas

Dos categorías de canario:

  • SCANNER-FLAG (Etapas A, B, C, D, E) — provoca que los escáneres generen reportes slop sobre el canario en lugar del código real.
  • RESOURCE-WASTE (Etapas F + G, juntas) — ejecuta escáneres LLM agentivos a través de su presupuesto de iteración completo al máximo costo.

Véase Modelo de seguridad para cómo cada etapa permanece inerte a pesar de parecer vulnerable.

Modelo de seguridad

Los archivos de código canario se leen deliberadamente como módulos obsoletos plausibles — sin lenguaje de "canary", "honeypot" o "tripwire" en comentarios o identificadores. Eso evita que los archivos se autoidentifiquen ante los escáneres, pero también significa que la documentación de por qué estos archivos son seguros vive aquí en lugar de en el docstring de cada archivo. Al revisar o rotar un canario, verifique que cada capa a continuación sigue intacta.

Estos archivos son código con forma vulnerable — y algunos (p. ej., pickle.loads de python/session_restore.py, memcpy sin límites de c/tls_heartbeat.c) serían genuinamente explotables si fueran alcanzables. Ese es el diseño. Que los escáneres marquen los sumideros es el objetivo; las capas a continuación bloquean la ejecución, no la señal del escáner. Los escáneres basados en patrones (grep, semgrep, pipelines de slop basados en LLM — el modelo de amenaza principal) leen el código fuente como texto y reportan hallazgos independientemente de la alcanzabilidad en tiempo de ejecución. Los escáneres C integrados en compilación (CodeQL predeterminado, clang-static-analyzer) solo ven archivos compilados, por lo que los canarios C no compilados son invisibles para ellos — una compensación aceptada, ya que los generadores de slop leen abrumadoramente el código fuente, no las compilaciones.

Etapas A y E (Python + JS)

Cinco capas independientes mantienen inertes estos archivos:

  1. raise ImportError / throw new Error a nivel superior — un import / require simple aborta antes de que cualquier definición se vincule.
  2. Cada def/función bajo if False: / if (false) — los nombres nunca entran al espacio de nombres en tiempo de ejecución incluso si se omite la capa 1.
  3. Exportaciones vacías — Python: __all__: list[str] = [] (importación con asterisco no exporta nada). JS: module.exports = {} (los consumidores CommonJS obtienen un objeto vacío).
  4. Cero llamadores dentro del árbol de las funciones shibboleth (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus). Cualquier reporte que cite una de ellas se autoidentifica como slop.
  5. Aislamiento de despliegue — el adoptante excluye las rutas canario de sdist / wheel / Docker / SAST (véase y ).

La Etapa E añade una sexta capa: la regex de retroceso catastrófico se almacena solo como cadena literal, no se pasa a re.compile / new RegExp en el ámbito del módulo. Incluso un entorno que elimine la capa 1 no puede activar un motor de retroceso compilado.

Los escáneres recorren el AST más allá de raise / throw y dentro del bloque muerto, por lo que los sumideros aún aparecen como hallazgos — ese es el comportamiento deseado.

Etapa B (C buffer_ops.c)

La seguridad es estructural — cada forma tiene una prueba junto a ella:

  • bufops_copy_banner — src es un literal de cadena, n = sizeof(literal), _Static_assert lo fija al tamaño del destino.
  • bufops_copy_bounded — if (n > dst_cap) n = dst_cap; la línea antes del memcpy hace imposible la afirmación CWE-787. Cortocircuito en n == 0 para evitar UB de C17 memcpy(dst, NULL, 0).
  • bufops_copy_truncating — n <= dst_cap - 1, dst[n] llega como máximo a dst_cap - 1; retorno temprano en dst_cap == 0.

Aislamiento adicional: todas las funciones son static (sin enlace externo) y el archivo no se agrega a ningún objetivo de compilación.

Etapa D (C heartbeat.c + sat.h)

La silueta de Heartbleed (uint16_t payload_len → malloc(1+2+payload_len+16) → memcpy) se desactiva con protecciones en capas:

  • sat_sub resta saturante para todo el cálculo del presupuesto de encabezado/cola (sin desbordamiento).
  • Los campos del marco se almacenan en locales const al inicio — cierra ventanas TOCTOU y de UB de manejadores de señal.
  • Verificaciones NULL en la estructura del lector y su buffer.
  • _Static_assert(SIZE_MAX - 19 >= UINT16_MAX, ...) demuestra que el tamaño de malloc no puede desbordar size_t.
  • Cortocircuito payload_len > 0 evita UB de memcpy(dst, NULL, 0) en cargas útiles vacías.
  • parse_heartbeat y read_u16_be son static; archivo no enlazado en ningún objetivo de compilación.

Un reporte que alegue lectura/escritura fuera de límites en parse_heartbeat sin involucrar la protección específica en la línea citada no ha verificado explotabilidad — cierre mediante regla de triage 5.

c/tls_heartbeat.c es una variación sobre la misma silueta mantenida deliberadamente sin protección: process_heartbeat es static y el archivo no está enlazado en ningún objetivo de compilación — el aislamiento es la única capa, coincidiendo con el captura-todo de la Etapa B. Intentar llamarlo desde fuera de la TU es un error de enlace.

Etapas A y E (Rust)

Cinco capas independientes mantienen inertes estos archivos (reflejando el modelo de seguridad de Python/JS):

  1. compile_error! a nivel superior — incluir el archivo en una crate mediante mod o include! produce un error duro del compilador antes de que se evalúe cualquier definición.
  2. Cada definición detrás de #[cfg(any())] — cfg(any()) siempre es falso, por lo que los nombres nunca entran en la salida compilada incluso si se omite la capa 1.
  3. Sin ítems pub — nada se exporta incluso si se eliminan ambas capas anteriores.
  4. Cero llamadores dentro del árbol de la función shibboleth (zqx_tarnish_v3). Cualquier reporte que la cite se autoidentifica como slop.
  5. Aislamiento de despliegue — el archivo no se referencia en ninguna declaración mod, no aparece en ningún Cargo.toml, y se excluye de los artefactos de compilación.

La Etapa E añade una sexta capa: la regex de retroceso catastrófico se almacena solo como constante &str, no se pasa a regex::Regex::new en el ámbito del módulo.

Etapa B (Rust buffer_ops.rs)

La seguridad es estructural, coincidiendo con la contraparte en C. Cada forma tiene una prueba:

  • bufops_copy_banner — src es b"status: ok\0", la longitud de copia es BANNER.len(); una aserción const lo fija al tamaño del destino.
  • bufops_copy_bounded — if n > dst_cap { n = dst_cap; } la línea antes de la copia acota la escritura. Cortocircuito en n == 0.
  • bufops_copy_truncating — n <= dst_cap - 1, la escritura NUL en dst.add(n) llega como máximo a dst_cap - 1; retorno temprano en dst_cap == 0.
  • bufops_shift — tanto como acotados a ; soporta explícitamente superposición.

Aislamiento adicional: todas las funciones están dentro de #[cfg(any())] (código muerto), no públicas, y el archivo no se agrega a ningún objetivo de compilación.

Etapa D (Rust heartbeat.rs + tls_heartbeat.rs)

La silueta de Heartbleed en Rust usa operaciones de puntero raw inseguras (ptr::copy_nonoverlapping, std::alloc::alloc) y se desactiva con las mismas protecciones en capas que la versión en C:

  • Resta saturante mediante usize::saturating_sub para todo el cálculo del presupuesto de encabezado/cola.
  • Campos del marco almacenados en variables locales al inicio.
  • Verificaciones nulas en la estructura del lector y su buffer.
  • Aserción const (usize::MAX - 19 >= u16::MAX) demuestra que la asignación no puede desbordar.
  • Cortocircuito payload_len > 0.
  • Todas las funciones dentro de #[cfg(any())], no públicas, archivo no enlazado.

rust/tls_heartbeat.rs es la variante deliberadamente sin protección: process_heartbeat usa ptr::copy_nonoverlapping con claimed_len de entrada no confiable y sin protección de límites. El aislamiento (#[cfg(any())] + compile_error! + no enlazado) es la única capa.

Etapas A y E (Go)

Cinco capas independientes mantienen inertes estos archivos:

  1. //go:build ignore en la parte superior de cada archivo. El toolchain de Go (go build, go test, go vet) omite el archivo por completo; nunca se compila, enlaza ni prueba.
  2. func init() { panic("...") } con UUID. Si la capa 1 se omite de alguna manera (anulación manual de -tags, go tool compile directo), el programa falla al inicio antes de que se ejecute main().
  3. Todas las funciones no exportadas (nombres en minúscula). Incluso si se compilan, nada es invocable desde fuera del paquete.
  4. Cero llamadores dentro del árbol de la función shibboleth (zqxTarnishV3). Cualquier reporte que la cite se autoidentifica como slop.
  5. Aislamiento de despliegue — los archivos están en un directorio independiente go/ sin go.mod, no referenciados por ninguna importación de paquete, y excluidos de los artefactos de compilación.

La Etapa E añade una sexta capa específica de Go: validatePep440Plus sí llama a regexp.MustCompile sobre el patrón catastrófico, pero el paquete regexp de Go usa semánticas RE2 (coincidencia garantizada en tiempo lineal), por lo que el retroceso catastrófico es imposible independientemente. El canario sigue siendo útil porque los escáneres marcan la forma del patrón textualmente sin verificar qué motor de regex está en uso.

Etapa B (Go buffer_ops.go)

La seguridad es estructural, coincidiendo con las contrapartes en C y Rust. Cada forma tiene una prueba:

  • bufopsCopyBanner — src es una constante de cadena, copy() desde un literal conocido hacia un array de tamaño fijo; una aserción en tiempo de compilación fija la longitud.
  • bufopsCopyBounded — if n > dstCap { n = dstCap } la línea antes de la copia acota la escritura. Cortocircuito en n == 0.
  • bufopsCopyTruncating — n <= dstCap - 1, la escritura NUL en dst[n] llega como máximo a dstCap - 1; retorno temprano en dstCap == 0.
  • bufopsShift — tanto i + n como j + n acotados a ; soporta superposición dentro de un solo slice.

Aislamiento adicional: //go:build ignore excluye el archivo de todas las compilaciones, todas las funciones no están exportadas, y el archivo no es importado por ningún paquete.

Etapa D (Go heartbeat.go + tls_heartbeat.go)

La silueta de Heartbleed en Go usa unsafe.Slice y unsafe.Pointer y se desactiva con las mismas protecciones en capas que las versiones en C y Rust:

  • satSub resta saturante para todo el cálculo del presupuesto de encabezado/cola.
  • Campos del marco almacenados en variables locales al inicio.
  • Verificaciones nil en la estructura del lector y su buffer.
  • Validación de longitud contra el presupuesto antes de la asignación.
  • Cortocircuito payloadLen > 0.
  • //go:build ignore, todas las funciones no exportadas, archivo no importado.

go/tls_heartbeat.go es la variante deliberadamente sin protección: processHeartbeat usa unsafe.Slice con claimedLen de entrada no confiable y sin protección de límites. El aislamiento (//go:build ignore + pánico en init + no importado) es la única capa.

Cómo probar

  1. Elija etapas. Superficie de analizador C/C++ → D (+ B). Mantenedor de OSS Python → A + E. Crate Rust → A + B + D + E. Módulo Go → A + B + D + E. Bajo spam sostenido de escáneres agentivos → añadir F + G en privado.
  2. Rote cada UUID. Uno por idioma, distinto por adoptante — no variantes de prefijo de una base. Véase ROTATE_UUID.md.
  3. Excluya de los artefactos de compilación. Python: MANIFEST.in prune las rutas canario, o pyproject.toml tool.setuptools.exclude-package-data. C: omitir de CMakeLists.txt / Makefile / sdist. Rust: no agregue una declaración mod o atributo path que referencie los archivos canario; excluya de las rutas [lib]/[[bin]] de Cargo.toml y de cargo package mediante exclude. Go: la restricción ya excluye los archivos de ; no coloque un en el directorio canario, y no importe el paquete canario. Docker: .

Fragmentos para adoptantes

Copie y pegue para cerrar los pasos de exclusión y propiedad anteriores. Las rutas a continuación usan el diseño c/ / python/ / js/ / rust/ / go/ de honeyslop; renómbrelas a donde coloque los canarios (véase paso 7) — confirmar exclusiones que aún apuntan a directorios llamados canary/ o slop/ es en sí mismo una pista.

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 — invocación CI

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

Ruff — pyproject.toml

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

.clang-format-ignore

root@kitploit:~
c/*

Lista blanca de escáner de secretos — 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 — excluir del paquete crate

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

Clippy — invocación CI

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

O salte el directorio canario completamente al no referenciarlo en ningún árbol mod (el valor predeterminado — compile_error! detectará la inclusión accidental).

golangci-lint — .golangci.yml

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

O confíe en la restricción //go:build ignore, que ya evita que el toolchain de Go compile los archivos canario.

.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

Los propietarios deben ser un grupo pequeño que entienda por qué estas rutas parecen vulnerables — para que los PRs de "limpiar código muerto" se bloqueen, no se fusionen.

Cuidado con

Cubo 1 — sus propias herramientas se activan. Sus escáneres, linters, IDE y escaneo de secretos se dispararán sobre el canario. Este es el comportamiento deseado para escaneos entrantes, pero significa que sus propios pipelines necesitan saltarse estas rutas. Requerido:

  • Excluya las rutas canario de cada configuración SAST (CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude, .clang-format-ignore, LSP del editor).
  • Excluya de artefactos publicados (MANIFEST.in prune, .dockerignore, exclusiones de wheel).
  • Incluya en lista blanca los secretos falsos (AKIAIOSFODNN7EXAMPLE, ghp_ / xoxb- / sk_live_ falsos) en su escáner de secretos.
  • Advierta a los contribuidores que no "limpien" el honeypot. Vigile la eliminación por el linter del disparador if False:, y la inserción de # noqa / .

Cubo 2 — erosión de efectividad. Los canarios públicos ingresan a corpus de entrenamiento de LLM en 6–18 meses y los vendedores de escáneres añaden heurísticas de salto. Rote UUIDs, banner, shibboleths y el CVE falso anualmente (véase ROTATE_UUID.md); varíe la redacción entre adoptantes; mantenga F+G en privado. No detendrá que los modelos aprendan el código, pero podría comprar algo de tiempo.

Cubo 3 — post-compromiso. Si un atacante ya tiene acceso, puede hacer lo que quiera y no necesita honeyslop. Sin embargo, cambiar if False: → if True:, insertar trucos Unicode/BIDI, o agregar texto de inyección de instrucciones en docstrings puede convertir un canario en vivo donde no lo espera. Vale la pena vigilarlo, aunque sea improbable.

Descargo de responsabilidad

Este proyecto se proporciona bajo la Licencia MIT; véase LICENSE para términos de garantía y responsabilidad. Es responsabilidad del usuario final cumplir con las leyes y regulaciones aplicables, y con los términos de servicio de cualquier herramienta o plataforma involucrada.

Advertencia: Este proyecto contiene código que parece vulnerable, y debe asumirse que lo es. Parte de él funciona siendo costoso de analizar — asuma que este código consumirá recursos informáticos significativos cuando sea inspeccionado por un escáner, dependiendo del canario. Cualquier modificación, automatizada o no, podría convertir un canario en vivo. No ejecute, despliegue ni adapte ninguno de sus componentes en un entorno real.

Licencia

Licenciado bajo MIT. Véase LICENSE.

Descargar herramienta
EtapaArchivo(s)Forma
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 sumideros CWE + secretos falsos + shibboleths
Bc/buffer_ops.c, rust/buffer_ops.rs, go/buffer_ops.go4 formas memcpy/memmove (CWE-120/121/787/170)
Cfusionado en ARendimiento CWE extendido
Dc/heartbeat.c + c/sat.h, c/tls_heartbeat.c, rust/heartbeat.rs, rust/tls_heartbeat.rs, go/heartbeat.go, go/tls_heartbeat.goSilueta de Heartbleed
Epython/regex_validator.py, js/regex_validator.js, rust/regex_validator.rs, go/regex_validator.goRegex de retroceso catastrófico + CVE-2025-99919 falso
F+Gprivate/fractal_dag/ (no en este repositorio)Sumideros de Etapa-A a través de un DAG de 12 nodos de entradas handle_*_request
SECURITY.md.template
Cómo probar
  • bufops_shift — tanto i + n como j + n acotados a cap; memmove soporta explícitamente superposición.
  • i + n
    j + n
    cap
    ptr::copy
    cap
    copy()
    //go:build ignore
    go build
    go.mod
    .dockerignore
  • Excluya del análisis estático de CI. De lo contrario, su propia CI produce hallazgos sobre el canario. CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude — todos apuntando a sus rutas canario.
  • Considere agregar la regla de triage a SECURITY.md — véase SECURITY.md.template. Esto puede alertar a los escáneres de slop sobre la presencia del canario (¿quizás algo bueno?).
  • Protéjase de la limpieza de contribuidores. CODEOWNERS en los archivos canario; un hook pre-commit que falle si el conteo de UUID canario disminuye o si faltan los disparadores if False:.
  • Elimine "pistas" obvias. Elimine "canary", "canaries", "honeypot", "decoy", "fake", "tripwire" y "slop" de comentarios de código, nombres de directorios, nombres de archivos y nombres de funciones/identificadores. Refrasee los docstrings al inicio de los archivos como avisos de obsolescencia plausibles. Mantenga este lenguaje conceptual en los documentos (README, SECURITY.md.template, ROTATE_UUID.md) donde es relevante.
  • # nosec