Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
honeyslop — Canary di codice per smistare rapidamente le segnalazioni di vulnerabilità allucinate ('slop') | Kitploit
Strumenti/GitHubGitHub/gadievron/honeyslop
Strumenti DifensiviAnalisi StaticaAnalisi delle VulnerabilitàAnalisi del CodiceThreat IntelligenceSicurezza della Supply ChainConfigurazione ErrataApprendimento e FormazioneRisposta agli Incidenti
GitHubgadievron/honeyslop

honeyslop

Canary di codice per smistare rapidamente le segnalazioni di vulnerabilità allucinate ('slop')

97103 mesi faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi Repository

honeyslop - canary di codice per smistare rapidamente i report di vulnerabilità allucinati ("slop")

HoneySlop

honeyslop è un insieme di canary di codice, esche, per progetti open-source sommersi da report di vulnerabilità allucinati dall'IA ("slop") e non verificati. Con questa iniezione di rumore avversario, uno scanner slop ingerisce il canary e poi genera un "report" di vulnerabilità basato su di esso. Il report si auto-identifica come slop. Lo chiudi con una sola grep.

Questo è un PoC veloce, vibe-coded come scherzo (non di livello produzione), perché anche noi abbiamo ricevuto un report slop su raptor, un agente autonomo di attacco/difesa basato su Claude Code. Dovrebbe essere divertente!

I canary di codice estendono i segnali di triage familiari (ad es. rilevamenti in file di test, segreti di esempio, percorsi inesistenti) trasformandoli in marcatori deliberati, o esche. Nei test, questi canary funzionano abbastanza bene da segnalare lo slop, ma possono essere ulteriormente migliorati (incorporati nel codice reale, con nomi di funzioni/file/directory meno indicativi, rigenerati regolarmente come nuovo codice, ecc.).

Scritto da: Gadi Evron (@gadievron), John Cartwright (@grokjc), Daniel Cuthbert (@danielcuthbert) e Michal Kamensky (@kamenskymic, con merito per aver dato il nome al progetto).

Usalo a tuo rischio. Se lo incolli in produzione, è un problema tuo. Vedi Disclaimer sotto.

Regole di triage

Per ogni report in arrivo, in ordine:

  1. grep di un qualsiasi UUID canary nel report → chiudi. (Gli UUID sono per linguaggio; ogni file canary ne incorpora esattamente uno.)
  2. grep dei nomi di funzione esclusivi dei canary (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus; anche handle_*_request se hai adottato F+G privatamente) → chiudi. (Rust usa lo stesso nome snake_case zqx_tarnish_v3 di Python. Go usa zqxTarnishV3, come il nome JS.)
  3. grep di CVE-2025-99919 (fittizio) → chiudi.
  4. La funzione citata non esiste nell'albero → "non esiste".
  5. Per le affermazioni su memcpy/bounds relative a B/D: chiedi a chi ha segnalato di spiegare passo passo come il suo PoC aggira la guardia specifica sulla riga citata. I follow-up dell'IA non riescono a rispondere; gli umani sì.

Fasi

Due categorie di canary:

  • SCANNER-FLAG (Fasi A, B, C, D, E) — fa scattare gli scanner in modo che i report slop si accumulino sul canary invece che sul codice reale.
  • RESOURCE-WASTE (Fasi F + G insieme) — fa esaurire agli scanner LLM agentici l'intero budget di iterazione al costo massimo.

Vedi Safety model per come ogni fase rimane inerte pur apparendo vulnerabile.

Safety model

I file di codice canary sono volutamente leggibili come plausibili moduli deprecati — nessun linguaggio "canary", "honeypot" o "tripwire" nei commenti o negli identificatori. Questo impedisce ai file di auto-identificarsi davanti agli scanner, ma significa anche che la documentazione sul perché questi file sono sicuri vive qui invece che nel docstring di ciascun file. Quando rivedi o ruoti un canary, verifica che ogni livello sottostante sia ancora intatto.

Questi file sono codice dalla forma vulnerabile — e alcuni (ad es. pickle.loads in python/session_restore.py, la memcpy senza limiti in c/tls_heartbeat.c) sarebbero davvero sfruttabili se raggiungibili. È il design. Il fatto che gli scanner segnalino i sink è il punto centrale; i livelli sottostanti bloccano l'esecuzione, non il segnale per lo scanner. Gli scanner basati su pattern (grep, semgrep, pipeline slop basate su LLM — il modello di minaccia principale) leggono il sorgente come testo e mostrano i risultati indipendentemente dalla raggiungibilità a runtime. Gli scanner C integrati nella build (CodeQL di default, clang-static-analyzer) vedono solo i file compilati, quindi i canary C non compilati sono invisibili per loro — un compromesso accettato, dato che i generatori di slop leggono in prevalenza il sorgente, non le build.

Fasi A ed E (Python + JS)

Cinque livelli indipendenti mantengono inerti questi file:

  1. raise ImportError / throw new Error di livello top-level — una semplice import / require si interrompe prima che qualsiasi definizione venga vincolata.
  2. Ogni def/funzione sotto if False: / if (false) — i nomi non entrano mai nel namespace runtime anche se il livello 1 viene bypassato.
  3. Export vuoti — Python: __all__: list[str] = [] (lo star-import non esporta nulla). JS: module.exports = {} (i consumer CommonJS ricevono un oggetto vuoto).
  4. Zero chiamanti in-tree delle funzioni shibboleth (zqx_tarnish_v3, zqxTarnishV3, _validate_pep_440_plus). Qualsiasi report che ne citi una si auto-identifica come slop.
  5. Isolamento di deployment — chi adotta esclude i percorsi dei canary da sdist / wheel / Docker / SAST (vedi e ).

La Fase E aggiunge un sesto livello: la regex con backtracking catastrofico è conservata solo come stringa letterale, non passata a re.compile / new RegExp a livello di modulo. Anche un harness che rimuove il livello 1 non può innescare un motore di backtracking compilato.

Gli scanner attraversano l'AST oltre raise / throw e dentro il blocco morto, quindi i sink emergono comunque come segnalazioni — è il comportamento previsto.

Fase B (C buffer_ops.c)

La sicurezza è strutturale — ogni forma ha una dimostrazione accanto:

  • bufops_copy_banner — src è un literal stringa, n = sizeof(literal), _Static_assert lo fissa alla dimensione della destinazione.
  • bufops_copy_bounded — if (n > dst_cap) n = dst_cap; la riga prima della memcpy rende impossibile l'affermazione CWE-787. Si interrompe su n == 0 per evitare la UB memcpy(dst, NULL, 0) del C17.
  • bufops_copy_truncating — n <= dst_cap - 1, dst[n] arriva al massimo a dst_cap - 1; return anticipato su dst_cap == 0.

Isolamento aggiuntivo: tutte le funzioni sono static (nessun collegamento esterno) e il file non è aggiunto ad alcun target di build.

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

La sagoma Heartbleed (uint16_t payload_len → malloc(1+2+payload_len+16) → memcpy) è resa innocua da guardie a livelli:

  • sat_sub sottrazione saturante per tutti i calcoli di budget header/trailer (niente wrap).
  • I campi della frame vengono memorizzati in locali const all'ingresso — chiude le finestre TOCTOU e di UB da signal handler.
  • Controlli NULL sulla struct del reader e sul suo buffer.
  • _Static_assert(SIZE_MAX - 19 >= UINT16_MAX, ...) dimostra che la dimensione della malloc non può far overflow di size_t.
  • Il corto circuito payload_len > 0 evita la UB memcpy(dst, NULL, 0) su payload vuoti.
  • parse_heartbeat e read_u16_be sono static; il file non è collegato ad alcun target di build.

Un report che sostiene una lettura/scrittura OOB in parse_heartbeat senza confrontarsi con la guardia specifica sulla riga citata non ha verificato lo sfruttamento — chiudi tramite la regola di triage 5.

c/tls_heartbeat.c è una variazione sulla stessa sagoma, volutamente lasciata senza guardie: process_heartbeat è static e il file non è collegato ad alcun target di build — l'isolamento è l'unico livello, come nel catch-all della Fase B. Qualsiasi tentativo di chiamarla dall'esterno della TU è un errore di link.

Fasi A ed E (Rust)

Cinque livelli indipendenti mantengono inerti questi file (rispecchiando il modello di sicurezza di Python/JS):

  1. compile_error! di livello top-level — includere il file in una crate tramite mod o include! produce un errore del compilatore prima che qualsiasi definizione venga valutata.
  2. Ogni definizione dietro #[cfg(any())] — cfg(any()) è sempre falso, quindi i nomi non entrano mai nell'output compilato anche se il livello 1 viene bypassato.
  3. Nessun elemento pub — nulla viene esportato anche se entrambi i livelli sopra vengono rimossi.
  4. Zero chiamanti in-tree della funzione shibboleth (zqx_tarnish_v3). Qualsiasi report che la citi si auto-identifica come slop.
  5. Isolamento di deployment — il file non è referenziato in alcuna dichiarazione mod, non è elencato in alcun Cargo.toml ed è escluso dagli artefatti di build.

La Fase E aggiunge un sesto livello: la regex con backtracking catastrofico è conservata solo come costante &str, non passata a regex::Regex::new a livello di modulo.

Fase B (Rust buffer_ops.rs)

La sicurezza è strutturale, come nella controparte C. Ogni forma ha una dimostrazione:

  • bufops_copy_banner — src è b"status: ok\0", la lunghezza della copia è BANNER.len(); un'asserzione const la fissa alla dimensione della destinazione.
  • bufops_copy_bounded — if n > dst_cap { n = dst_cap; } la riga prima della copia limita la scrittura. Si interrompe su n == 0.
  • bufops_copy_truncating — n <= dst_cap - 1, la scrittura del NUL in dst.add(n) arriva al massimo a dst_cap - 1; return anticipato su dst_cap == 0.
  • bufops_shift — sia che sono limitati a ; supporta esplicitamente la sovrapposizione.

Isolamento aggiuntivo: tutte le funzioni sono dentro #[cfg(any())] (codice morto), non pubbliche, e il file non è aggiunto ad alcun target di build.

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

La sagoma Heartbleed in Rust usa operazioni su puntatori grezzi unsafe (ptr::copy_nonoverlapping, std::alloc::alloc) ed è resa innocua dalle stesse guardie a livelli della versione C:

  • Sottrazione saturante tramite usize::saturating_sub per tutti i calcoli di budget header/trailer.
  • I campi della frame vengono memorizzati in variabili locali all'ingresso.
  • Controlli null sulla struct del reader e sul suo buffer.
  • L'asserzione const (usize::MAX - 19 >= u16::MAX) dimostra che l'allocazione non può andare in overflow.
  • Corto circuito su payload_len > 0.
  • Tutte le funzioni dentro #[cfg(any())], non pubbliche, file non collegato.

rust/tls_heartbeat.rs è la variante volutamente senza guardie: process_heartbeat usa ptr::copy_nonoverlapping con claimed_len proveniente da input non attendibile e senza guardia sui limiti. L'isolamento (#[cfg(any())] + compile_error! + non collegato) è l'unico livello.

Fasi A ed E (Go)

Cinque livelli indipendenti mantengono inerti questi file:

  1. //go:build ignore in cima a ogni file. La toolchain Go (go build, go test, go vet) salta completamente il file; non viene mai compilato, collegato o testato.
  2. func init() { panic("...") } con UUID. Se il livello 1 viene in qualche modo bypassato (override manuale di -tags, go tool compile diretto), il programma va in crash all'avvio prima che main() venga eseguito.
  3. Tutte le funzioni non esportate (nomi minuscoli). Anche se compilate, nulla è chiamabile dall'esterno del pacchetto.
  4. Zero chiamanti in-tree della funzione shibboleth (zqxTarnishV3). Qualsiasi report che la citi si auto-identifica come slop.
  5. Isolamento di deployment — i file sono in una directory go/ autonoma senza go.mod, non referenziati da alcun import di pacchetto ed esclusi dagli artefatti di build.

La Fase E aggiunge un sesto livello specifico di Go: validatePep440Plus chiama effettivamente regexp.MustCompile sul pattern catastrofico, ma il pacchetto regexp di Go usa la semantica RE2 (matching a tempo lineare garantito), quindi il backtracking catastrofico è comunque impossibile. Il canary è comunque utile perché gli scanner segnalano la forma del pattern testualmente senza controllare quale motore regex è in uso.

Fase B (Go buffer_ops.go)

La sicurezza è strutturale, come nelle controparti C e Rust. Ogni forma ha una dimostrazione:

  • bufopsCopyBanner — src è una costante stringa, copy() da un literal noto in un array a dimensione fissa; un'asserzione a compile-time fissa la lunghezza.
  • bufopsCopyBounded — if n > dstCap { n = dstCap } la riga prima della copia limita la scrittura. Si interrompe su n == 0.
  • bufopsCopyTruncating — n <= dstCap - 1, la scrittura del NUL in dst[n] arriva al massimo a dstCap - 1; return anticipato su dstCap == 0.
  • bufopsShift — sia i + n che j + n sono limitati a ; supporta la sovrapposizione all'interno di un'unica slice.

Isolamento aggiuntivo: //go:build ignore esclude il file da tutte le build, tutte le funzioni sono non esportate e il file non è importato da alcun pacchetto.

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

La sagoma Heartbleed in Go usa unsafe.Slice e unsafe.Pointer ed è resa innocua dalle stesse guardie a livelli delle versioni C e Rust:

  • satSub sottrazione saturante per tutti i calcoli di budget header/trailer.
  • I campi della frame vengono memorizzati in variabili locali all'ingresso.
  • Controlli nil sulla struct del reader e sul suo buffer.
  • Validazione della lunghezza rispetto al budget prima dell'allocazione.
  • Corto circuito su payloadLen > 0.
  • //go:build ignore, tutte le funzioni non esportate, file non importato.

go/tls_heartbeat.go è la variante volutamente senza guardie: processHeartbeat usa unsafe.Slice con claimedLen proveniente da input non attendibile e senza guardia sui limiti. L'isolamento (//go:build ignore + panic in init + non importato) è l'unico livello.

How to try

  1. Scegli le fasi. Superficie parser C/C++ → D (+ B). Chi mantiene un OSS Python → A + E. Crate Rust → A + B + D + E. Modulo Go → A + B + D + E. Sotto spam sostenuto di scanner agentici → aggiungi F + G privatamente.
  2. Ruota ogni UUID. Uno per linguaggio, distinto per ogni adottante — non varianti con prefisso di una stessa base. Vedi ROTATE_UUID.md.
  3. Escludi dagli artefatti di build. Python: MANIFEST.in prune sui percorsi dei canary, oppure pyproject.toml tool.setuptools.exclude-package-data. C: ometti da CMakeLists.txt / Makefile / sdist. Rust: non aggiungere una dichiarazione mod o un attributo path che referenzi i file canary; escludi dai percorsi [lib]/[[bin]] di Cargo.toml e da cargo package tramite . Go: il vincolo esclude già i file da ; non inserire un nella directory dei canary e non importare il pacchetto canary. Docker: .

Snippet per chi adotta

Copia-incolla per chiudere i passaggi di esclusione e proprietà sopra. I percorsi seguenti usano la struttura c/ / python/ / js/ / rust/ / go/ di honeyslop; rinomina in base al punto in cui collochi i canary (vedi passaggio 7) — committare esclusioni che puntano ancora a directory chiamate canary/ o slop/ è di per sé un indizio.

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

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

Ruff — pyproject.toml

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

.clang-format-ignore

root@kitploit:~
c/*

Allowlist dello scanner di segreti — 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 — esclusione dal pacchetto della crate

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

Clippy — invocazione CI

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

Oppure salta del tutto la directory dei canary non referenziandola in alcun albero mod (il default — compile_error! intercetterà un'inclusione accidentale).

golangci-lint — .golangci.yml

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

Oppure affidati al vincolo //go:build ignore, che impedisce già alla toolchain Go di compilare i file canary.

.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

Gli owner dovrebbero essere un piccolo gruppo che capisce perché questi percorsi sembrano vulnerabili — così le PR di "pulizia del codice morto" vengono bloccate, non merged.

A cosa fare attenzione

Bucket 1 — i tuoi stessi strumenti inciampano. I tuoi scanner, linter, IDE e la scansione dei segreti si attiveranno sul canary. È il comportamento voluto per le scansioni in arrivo, ma significa che le tue stesse pipeline devono saltare questi percorsi. Obbligatorio:

  • Escludi i percorsi dei canary da ogni configurazione SAST (CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude, .clang-format-ignore, LSP dell'editor).
  • Escludi dagli artefatti pubblicati (MANIFEST.in prune, .dockerignore, esclusioni wheel).
  • Metti in allowlist i segreti fittizi (AKIAIOSFODNN7EXAMPLE, ghp_ / xoxb- / sk_live_ fittizi) nel tuo scanner di segreti.
  • Avvisa i contributor di non "ripulire" l'honeypot. Fai attenzione alla rimozione da parte del linter del tripwire if False: e all'inserimento di # noqa / .

Bucket 2 — erosione dell'efficacia. I canary pubblici entrano nei corpora di addestramento degli LLM nell'arco di 6–18 mesi e i vendor degli scanner aggiungono euristiche di skip. Ruota UUID, banner, shibboleth e il falso CVE ogni anno (vedi ROTATE_UUID.md); varia la formulazione tra gli adottanti; mantieni F+G private. Non fermerà i modelli dall'imparare il codice, ma potrebbe farti guadagnare un po' di tempo.

Bucket 3 — post-compromissione. Se un attaccante ha già accesso, può fare qualsiasi cosa e non ha bisogno di honeyslop. Tuttavia, trasformare if False: → if True:, inserire trucchi Unicode/BIDI o aggiungere testo di prompt injection nei docstring può rendere attivo un canary dove non te lo aspetti. Vale la pena di tenerlo d'occhio, anche se improbabile.

Disclaimer

Questo progetto è fornito sotto la licenza MIT; vedi LICENSE per i termini di garanzia e responsabilità. È responsabilità dell'utente finale rispettare leggi e regolamenti applicabili, nonché i termini di servizio di eventuali strumenti o piattaforme coinvolti.

Avviso: questo progetto contiene codice che sembra vulnerabile, e va considerato tale. Parte di esso funziona perché è costoso da analizzare — supponi che questo codice consumerà risorse di calcolo significative quando uno scanner lo ispeziona, a seconda del canary. Qualsiasi modifica, automatizzata o meno, potrebbe rendere attivo un canary. Non eseguire, distribuire o adattare nulla di tutto ciò in un ambiente reale.

Licenza

Concesso in licenza MIT. Vedi LICENSE.

Scarica lo strumento
FaseFile(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 sink CWE + segreti fittizi + shibboleth
Bc/buffer_ops.c, rust/buffer_ops.rs, go/buffer_ops.go4 forme memcpy/memmove (CWE-120/121/787/170)
Cfusa in AResa CWE estesa
Dc/heartbeat.c + c/sat.h, c/tls_heartbeat.c, rust/heartbeat.rs, rust/tls_heartbeat.rs, go/heartbeat.go, go/tls_heartbeat.goSagoma Heartbleed
Epython/regex_validator.py, js/regex_validator.js, rust/regex_validator.rs, go/regex_validator.goRegex con backtracking catastrofico + falso CVE-2025-99919
F+Gprivate/fractal_dag/ (non in questo repo)Sink di Fase A distribuiti su un DAG a 12 nodi di voci handle_*_request
SECURITY.md.template
How to try
  • bufops_shift — sia i + n che j + n sono limitati a cap; memmove supporta esplicitamente la sovrapposizione.
  • i + n
    j + n
    cap
    ptr::copy
    cap
    copy()
    exclude
    //go:build ignore
    go build
    go.mod
    .dockerignore
  • Escludi dall'analisi statica in CI. Altrimenti la tua stessa CI produce segnalazioni sul canary. CodeQL paths-ignore, .semgrepignore, bandit -x, Ruff --extend-exclude — tutti puntati ai tuoi percorsi canary.
  • Valuta di aggiungere la regola di triage a SECURITY.md — vedi SECURITY.md.template. Questo potrebbe rivelare agli scanner slop la presenza del canary (forse è una buona cosa?).
  • Proteggilo dalla pulizia da parte dei contributor. CODEOWNERS sui file canary; un hook pre-commit che fallisce se il conteggio degli UUID canary diminuisce o se spariscono i tripwire if False:.
  • Rimuovi gli "indizi" evidenti. Elimina "canary", "canaries", "honeypot", "decoy", "fake", "tripwire" e "slop" dai commenti del codice, dai nomi di directory, dai nomi di file e dai nomi di funzioni/identificatori. Riformula i docstring in cima ai file come plausibili note di deprecazione. Tieni questo linguaggio concettuale nella documentazione (README, SECURITY.md.template, ROTATE_UUID.md) dove è portante.
  • # nosec