Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
honeyslop — Code canaries pour trier rapidement les rapports de vulnérabilités hallucinées ('slop') | Kitploit
Outils/GitHubGitHub/gadievron/honeyslop
Outils DéfensifsAnalyse StatiqueAnalyse des VulnérabilitésAnalyse de CodeRenseignement sur les MenacesSécurité de la Chaîne LogistiqueMauvaise ConfigurationApprentissage et ÉducationRéponse aux Incidents
GitHubgadievron/honeyslop

honeyslop

Code canaries pour trier rapidement les rapports de vulnérabilités hallucinées ('slop')

9710il y a 3 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Voir le dépôt

honeyslop - canaris de code pour trier rapidement les rapports de vulnérabilité hallucinés (« slop »)

HoneySlop

honeyslop est un ensemble de canaris de code, des leurres, destinés aux projets open-source submergés par des rapports de vulnérabilité hallucinés par l'IA (« slop ») et non vérifiés. Avec une telle injection de bruit adversarial, un scanner slop ingère le canari, puis génère un « rapport » de vulnérabilité basé sur celui-ci. Le rapport s'identifie lui-même comme du slop. Clôturez-le en un seul grep.

Ceci est un PoC rapide, codé au feeling comme une blague (pas de qualité production), car nous avons nous-mêmes reçu un rapport slop sur raptor, un agent autonome d'attaque/défense basé sur Claude Code. Ce devrait être amusant !

Les canaris de code étendent les signaux de triage familiers (par exemple, les détections dans les fichiers de test, les secrets d'exemple, les chemins inexistants) en marqueurs délibérés, ou leurres. Lors des tests, ces canaris fonctionnent suffisamment bien pour signaler du slop, mais ils peuvent être encore améliorés (intégrés dans du code réel, noms de fonctions/fichiers/répertoires moins indicateurs, régénérés régulièrement comme nouveau code, etc.).

Écrit par : Gadi Evron (@gadievron), John Cartwright (@grokjc), Daniel Cuthbert (@danielcuthbert) et Michal Kamensky (@kamenskymic, avec des remerciements pour avoir nommé le projet).

Utilisation à vos propres risques. Si vous collez ceci en production, c'est votre problème. Voir Avertissement ci-dessous.

Règles de triage

Pour chaque rapport entrant, dans l'ordre :

  1. grep tout UUID de canari dans le rapport → fermer. (Les UUID sont propres à chaque langage ; chaque fichier canari en intègre exactement un.)
  2. grep les noms de fonction propres aux canaris (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus ; également handle_*_request si vous avez adopté F+G en privé) → fermer. (Rust utilise le même nom snake_case zqx_tarnish_v3 que Python. Go utilise zqxTarnishV3, correspondant au nom JS.)
  3. grep CVE-2025-99919 (faux) → fermer.
  4. La fonction citée n'existe pas dans l'arborescence → « n'existe pas ».
  5. Pour les affirmations de memcpy/dépassement de limites sur B/D : demander au rapporteur d'expliquer comment son PoC contourne la protection spécifique sur la ligne citée. Les suivis par IA ne peuvent pas répondre ; les humains le peuvent.

Étapes

Deux catégories de canaris :

  • SCANNER-FLAG (Étapes A, B, C, D, E) — déclenche les scanners afin que les rapports slop s'accumulent sur le canari au lieu du code réel.
  • RESOURCE-WASTE (Étapes F + G, ensemble) — fait passer les scanners LLM agentiques à travers leur budget d'itération complet au coût maximum.

Voir Modèle de sécurité pour savoir comment chaque étape reste inerte malgré son apparence vulnérable.

Modèle de sécurité

Les fichiers de code canari se lisent délibérément comme des modules plausibles et obsolètes — aucun terme « canari », « honeypot » ou « tripwire » dans les commentaires ou les identifiants. Cela empêche les fichiers de s'identifier eux-mêmes aux scanners, mais cela signifie aussi que la documentation pourquoi ces fichiers sont sûrs se trouve ici plutôt que dans la docstring de chaque fichier. Lors de la révision ou de la rotation d'un canari, vérifiez que chaque couche ci-dessous est toujours intacte.

Ces fichiers sont du code à forme vulnérable — et certains (par exemple pickle.loads dans python/session_restore.py, le memcpy sans limite dans c/tls_heartbeat.c) seraient véritablement exploitables s'ils étaient atteignables. C'est le but recherché. Le fait que les scanners signalent les sinks est l'objectif ; les couches ci-dessous bloquent l'exécution, pas le signal du scanner. Les scanners basés sur des motifs (grep, semgrep, pipelines slop basés sur LLM — le modèle de menace principal) lisent le code source en tant que texte et remontent les résultats indépendamment de l'atteignabilité à l'exécution. Les scanners C intégrés à la compilation (CodeQL par défaut, clang-static-analyzer) ne voient que les fichiers compilés, donc les canaris C non compilés leur sont invisibles — un compromis acceptable, car les générateurs de slop lisent massivement le code source, pas les binaires.

Étapes A et E (Python + JS)

Cinq couches indépendantes maintiennent ces fichiers inertes :

  1. raise ImportError / throw new Error au niveau supérieur — un simple import / require avorte avant que toute définition ne soit liée.
  2. Chaque def/fonction sous if False: / if (false) — les noms n'entrent jamais dans l'espace de noms d'exécution même si la couche 1 est contournée.
  3. Exports vides — Python : __all__: list[str] = [] (l'import étoile n'exporte rien). JS : module.exports = {} (les consommateurs CommonJS obtiennent un objet vide).
  4. Zéro appelant dans l'arborescence des fonctions shibboleth (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus). Tout rapport en citant une s'identifie comme du slop.
  5. Isolement de déploiement — l'adoptant exclut les chemins canari de sdist / wheel / Docker / SAST (voir et ).

L'étape E ajoute une sixième couche : la regex à rétro-traçage catastrophique est stockée uniquement comme un littéral de chaîne, non passée à re.compile / new RegExp au niveau du module. Même un harnais qui retire la couche 1 ne peut pas déclencher un moteur de rétro-traçage compilé.

Les scanners parcourent l'AST au-delà du raise / throw et dans le bloc mort, donc les sinks apparaissent toujours comme des résultats — c'est le comportement souhaité.

Étape B (C buffer_ops.c)

La sécurité est structurelle — chaque forme est accompagnée d'une preuve :

  • bufops_copy_banner — src est un littéral de chaîne, n = sizeof(literal), _Static_assert le verrouille à la taille de destination.
  • bufops_copy_bounded — if (n > dst_cap) n = dst_cap; la ligne avant le memcpy rend l'affirmation CWE-787 impossible. Court-circuits sur n == 0 pour éviter le comportement indéfini C17 memcpy(dst, NULL, 0).
  • bufops_copy_truncating — n <= dst_cap - 1, dst[n] atteint au maximum dst_cap - 1 ; retour anticipé sur dst_cap == 0.

Isolement supplémentaire : toutes les fonctions sont static (pas de lien externe) et le fichier n'est ajouté à aucune cible de compilation.

Étape D (C heartbeat.c + sat.h)

La silhouette Heartbleed (uint16_t payload_len → malloc(1+2+payload_len+16) → memcpy) est désarmée par des gardes en couches :

  • sat_sub soustraction saturante pour tous les calculs de budget d'en-tête/queue (pas de débordement).
  • Les champs de trame sont mis en cache dans des const locales à l'entrée — ferme les fenêtres TOCTOU et de comportement indéfini des gestionnaires de signaux.
  • Vérifications NULL sur la structure de lecture et son tampon.
  • _Static_assert(SIZE_MAX - 19 >= UINT16_MAX, ...) prouve que la taille malloc ne peut pas déborder size_t.
  • payload_len > 0 court-circuite pour éviter le comportement indéfini memcpy(dst, NULL, 0) sur les charges utiles vides.
  • parse_heartbeat et read_u16_be sont static ; fichier non lié à aucune cible de compilation.

Un rapport alléguant une lecture/écriture hors limites dans parse_heartbeat sans s'engager avec la garde spécifique sur la ligne citée n'a pas vérifié l'exploitabilité — fermer via la règle de triage 5.

c/tls_heartbeat.c est une variante de la même silhouette délibérément laissée sans garde : process_heartbeat est static et le fichier n'est lié à aucune cible de compilation — l'isolement est la seule couche, correspondant au filet de sécurité de l'étape B. Tenter de l'appeler depuis l'extérieur de l'unité de traduction est une erreur de lien.

Étapes A et E (Rust)

Cinq couches indépendantes maintiennent ces fichiers inertes (miroir du modèle de sécurité Python/JS) :

  1. compile_error! au niveau supérieur — inclure le fichier dans une crate via mod ou include! produit une erreur de compilation dure avant l'évaluation de toute définition.
  2. Chaque définition derrière #[cfg(any())] — cfg(any()) est toujours faux, donc les noms n'entrent jamais dans la sortie compilée même si la couche 1 est contournée.
  3. Aucun élément pub — rien n'est exporté même si les deux couches ci-dessus sont retirées.
  4. Zéro appelant dans l'arborescence de la fonction shibboleth (zqx_tarnish_v3). Tout rapport en citant une s'identifie comme du slop.
  5. Isolement de déploiement — le fichier n'est référencé dans aucune instruction mod, n'est listé dans aucun Cargo.toml, et est exclu des artefacts de compilation.

L'étape E ajoute une sixième couche : la regex à rétro-traçage catastrophique est stockée uniquement comme une constante &str, non passée à regex::Regex::new au niveau du module.

Étape B (Rust buffer_ops.rs)

La sécurité est structurelle, correspondant à l'homologue C. Chaque forme a une preuve :

  • bufops_copy_banner — src est b"status: ok\0", la longueur de copie est BANNER.len() ; une assertion const la verrouille à la taille de destination.
  • bufops_copy_bounded — if n > dst_cap { n = dst_cap; } la ligne avant la copie borne l'écriture. Court-circuits sur n == 0.
  • bufops_copy_truncating — n <= dst_cap - 1, l'écriture NUL à dst.add(n) atteint au maximum dst_cap - 1 ; retour anticipé sur dst_cap == 0.
  • bufops_shift — et sont tous deux bornés à ; supporte explicitement le chevauchement.

Isolement supplémentaire : toutes les fonctions sont à l'intérieur de #[cfg(any())] (code mort), non publiques, et le fichier n'est ajouté à aucune cible de compilation.

Étape D (Rust heartbeat.rs + tls_heartbeat.rs)

La silhouette Heartbleed en Rust utilise des opérations de pointeur brut unsafe (ptr::copy_nonoverlapping, std::alloc::alloc) et est désarmée par les mêmes gardes en couches que la version C :

  • Soustraction saturante via usize::saturating_sub pour tous les calculs de budget d'en-tête/queue.
  • Champs de trame mis en cache dans des variables locales à l'entrée.
  • Vérifications NULL sur la structure de lecture et son tampon.
  • Assertion constante (usize::MAX - 19 >= u16::MAX) prouve que l'allocation ne peut pas déborder.
  • payload_len > 0 court-circuite.
  • Toutes les fonctions à l'intérieur de #[cfg(any())], non publiques, fichier non lié.

rust/tls_heartbeat.rs est la variante délibérément non gardée : process_heartbeat utilise ptr::copy_nonoverlapping avec claimed_len provenant d'une entrée non fiable et sans garde de limites. L'isolement (#[cfg(any())] + compile_error! + non lié) est la seule couche.

Étapes A et E (Go)

Cinq couches indépendantes maintiennent ces fichiers inertes :

  1. //go:build ignore en haut de chaque fichier. La chaîne d'outils Go (go build, go test, go vet) ignore complètement le fichier ; il n'est jamais compilé, lié ou testé.
  2. func init() { panic("...") } avec UUID. Si la couche 1 est contournée d'une manière ou d'une autre (remplacement manuel par -tags, go tool compile brut), le programme plante au démarrage avant que main() ne s'exécute.
  3. Toutes les fonctions non exportées (noms en minuscules). Même compilé, rien n'est appelable depuis l'extérieur du package.
  4. Zéro appelant dans l'arborescence de la fonction shibboleth (zqxTarnishV3). Tout rapport en citant une s'identifie comme du slop.
  5. Isolement de déploiement — les fichiers sont dans un répertoire go/ autonome sans go.mod, non référencés par aucune importation de package, et exclus des artefacts de compilation.

L'étape E ajoute une sixième couche spécifique à Go : validatePep440Plus appelle effectivement regexp.MustCompile sur le motif catastrophique, mais le package regexp de Go utilise la sémantique RE2 (correspondance en temps linéaire garanti), donc le rétro-traçage catastrophique est impossible quoi qu'il arrive. Le canari est toujours utile car les scanners signalent textuellement la forme du motif sans vérifier quel moteur regex est utilisé.

Étape B (Go buffer_ops.go)

La sécurité est structurelle, correspondant aux homologues C et Rust. Chaque forme a une preuve :

  • bufopsCopyBanner — src est une constante de chaîne, copy() à partir d'un littéral connu dans un tableau de taille fixe ; une assertion au moment de la compilation verrouille la longueur.
  • bufopsCopyBounded — if n > dstCap { n = dstCap } la ligne avant la copie borne l'écriture. Court-circuits sur n == 0.
  • bufopsCopyTruncating — n <= dstCap - 1, l'écriture NUL à dst[n] atteint au maximum dstCap - 1 ; retour anticipé sur dstCap == 0.
  • bufopsShift — i + n et j + n sont tous deux bornés à ; supporte le chevauchement dans une seule tranche.

Isolement supplémentaire : //go:build ignore exclut le fichier de toute compilation, toutes les fonctions sont non exportées, et le fichier n'est importé par aucun package.

Étape D (Go heartbeat.go + tls_heartbeat.go)

La silhouette Heartbleed en Go utilise unsafe.Slice et unsafe.Pointer et est désarmée par les mêmes gardes en couches que les versions C et Rust :

  • satSub soustraction saturante pour tous les calculs de budget d'en-tête/queue.
  • Champs de trame mis en cache dans des variables locales à l'entrée.
  • Vérifications nil sur la structure de lecture et son tampon.
  • Validation de longueur par rapport au budget avant allocation.
  • payloadLen > 0 court-circuite.
  • //go:build ignore, toutes les fonctions non exportées, fichier non importé.

go/tls_heartbeat.go est la variante délibérément non gardée : processHeartbeat utilise unsafe.Slice avec claimedLen provenant d'une entrée non fiable et sans garde de limites. L'isolement (//go:build ignore + init panic + non importé) est la seule couche.

Comment essayer

  1. Choisissez les étapes. Surface d'analyseur C/C++ → D (+ B). Mainteneur OSS Python → A + E. Crate Rust → A + B + D + E. Module Go → A + B + D + E. Sous spam soutenu de scanner agentique → ajouter F + G en privé.
  2. Faites tourner chaque UUID. Un par langage, distinct par adoptant — pas des variantes de préfixe d'une même base. Voir ROTATE_UUID.md.
  3. Exclure des artefacts de compilation. Python : MANIFEST.in prune des chemins canari, ou pyproject.toml tool.setuptools.exclude-package-data. C : omettre de CMakeLists.txt / Makefile / sdist. Rust : ne pas ajouter d'instruction mod ou d'attribut path référençant les fichiers canari ; exclure de Cargo.toml [lib]/[[bin]] paths et de cargo package via exclude. Go : la contrainte exclut déjà les fichiers de ; ne pas placer de dans le répertoire canari, et ne pas importer le package canari. Docker : .

Extraits pour adoptants

Copiez-collez pour finaliser les étapes d'exclusion et de propriété ci-dessus. Les chemins ci-dessous utilisent la disposition c/ / python/ / js/ / rust/ / go/ de honeyslop ; renommez vers l'endroit où vous placez les canaris (voir étape 7) — valider des exclusions qui pointent encore vers des répertoires nommés canary/ ou slop/ est en soi un signe.

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 — invocation CI

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

Ruff — pyproject.toml

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

.clang-format-ignore

root@kitploit:~
c/*

Liste blanche de scanneur de secrets — 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 — exclure du package crate

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

Clippy — invocation CI

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

Ou ignorez complètement le répertoire canari en ne le référençant dans aucune arborescence mod (le comportement par défaut — compile_error! attrapera une inclusion accidentelle).

golangci-lint — .golangci.yml

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

Ou comptez sur la contrainte //go:build ignore, qui empêche déjà la chaîne d'outils Go de compiler les fichiers canari.

.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

Les propriétaires devraient être un petit groupe qui comprend pourquoi ces chemins semblent vulnérables — afin que les PR « nettoyer le code mort » soient bloquées, pas fusionnées.

Attention à

Seau 1 — vos propres outils déclenchent. Vos scanners, linters, IDE et scanneurs de secrets vont se déclencher sur le canari. C'est le comportement attendu pour les analyses entrantes mais cela signifie que vos propres pipelines doivent ignorer ces chemins. Requis :

  • Exclure les chemins canari de chaque config SAST (CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude, .clang-format-ignore, LSP de l'éditeur).
  • Exclure des artefacts publiés (MANIFEST.in prune, .dockerignore, exclusions de wheel).
  • Mettre en liste blanche les faux secrets (AKIAIOSFODNN7EXAMPLE, faux ghp_ / xoxb- / sk_live_) dans votre scanneur de secrets.
  • Avertir les contributeurs de ne pas « nettoyer » le honeypot. Surveiller la suppression du déclencheur if False: par le linter, et l'insertion de # noqa / .

Seau 2 — érosion de l'efficacité. Les canaris publics entrent dans les corpus d'entraînement des LLM sur 6 à 18 mois et les fournisseurs de scanners ajoutent des heuristiques de saut. Faites tourner les UUID, la bannière, les shibboleths et le faux CVE annuellement (voir ROTATE_UUID.md) ; variez le libellé entre adoptants ; garder F+G privé. Cela n'empêchera pas les modèles d'apprendre le code, mais pourrait vous faire gagner du temps.

Seau 3 — après compromission. Si un attaquant a déjà accès, il peut faire ce qu'il veut et n'a pas besoin de honeyslop. Cependant, changer if False: → if True:, insérer des astuces Unicode/BIDI, ou ajouter du texte d'injection de prompt dans les docstrings peut transformer un canari en code vivant là où vous ne l'attendez pas. À surveiller, bien que peu probable.

Avertissement

Ce projet est fourni sous licence MIT ; voir LICENSE pour les conditions de garantie et de responsabilité. Il incombe à l'utilisateur final de se conformer aux lois et réglementations applicables, ainsi qu'aux conditions d'utilisation des outils ou plateformes impliqués.

Avertissement : Ce projet contient du code qui semble vulnérable et doit être considéré comme tel. Une partie de celui-ci fonctionne en étant coûteuse à analyser — supposez que ce code consommera des ressources de calcul significatives lorsqu'il sera inspecté par un scanner, selon le canari. Toute modification, automatisée ou non, pourrait transformer un canari en code vivant. N'exécutez, déployez ou adaptez aucun de ces éléments dans un environnement réel.

Licence

Sous licence MIT. Voir LICENSE.

Télécharger l’outil
ÉtapeFichier(s)Forme
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 sinks CWE + faux secrets + shibboleths
Bc/buffer_ops.c, rust/buffer_ops.rs, go/buffer_ops.go4 formes memcpy/memmove (CWE-120/121/787/170)
Cfusionné dans ACouverture CWE étendue
Dc/heartbeat.c + c/sat.h, c/tls_heartbeat.c, rust/heartbeat.rs, rust/tls_heartbeat.rs, go/heartbeat.go, go/tls_heartbeat.goSilhouette Heartbleed
Epython/regex_validator.py, js/regex_validator.js, rust/regex_validator.rs, go/regex_validator.goRegex à rétro-traçage catastrophique + faux CVE-2025-99919
F+Gprivate/fractal_dag/ (pas dans ce dépôt)Sinks de l'étape A à travers un DAG de 12 nœuds d'entrées handle_*_request
SECURITY.md.template
Comment essayer
  • bufops_shift — i + n et j + n sont tous deux bornés à cap ; memmove supporte explicitement le chevauchement.
  • i + n
    j + n
    cap
    ptr::copy
    cap
    copy()
    //go:build ignore
    go build
    go.mod
    .dockerignore
  • Exclure de l'analyse statique CI. Sinon votre propre CI produira des résultats sur le canari. CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude — tous pointés vers vos chemins canari.
  • Envisagez d'ajouter la règle de triage à SECURITY.md — voir SECURITY.md.template. Cela pourrait révéler la présence du canari aux scanners slop (peut-être une bonne chose ?).
  • Protéger du nettoyage par les contributeurs. CODEOWNERS sur les fichiers canari ; un hook pre-commit qui échoue si le nombre d'UUID canari diminue ou si les déclencheurs if False: disparaissent.
  • Supprimer les « signes » évidents. Retirez « canari », « canaris », « honeypot », « leurre », « faux », « tripwire » et « slop » des commentaires de code, noms de répertoires, noms de fichiers et noms de fonctions/identifiants. Reformulez les docstrings en haut de fichier comme des avis d'obsolescence plausibles. Gardez ce langage conceptuel dans la documentation (README, SECURITY.md.template, ROTATE_UUID.md) là où il est porteur de sens.
  • # nosec