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
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')

971033 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 →
Vedi Repository
Condividi

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.)
  • 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.)
  • grep di CVE-2025-99919 (fittizio) → chiudi.
  • La funzione citata non esiste nell'albero → "non esiste".
  • 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.
    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

    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 SECURITY.md.template e How to try).

    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.
    • bufops_shift — sia i + n che j + n sono limitati a cap; memmove supporta esplicitamente la sovrapposizione.

    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 i + n che j + n sono limitati a cap; ptr::copy 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 cap; copy() 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 exclude. Go: il vincolo //go:build ignore esclude già i file da go build; non inserire un go.mod nella directory dei canary e non importare il pacchetto canary. Docker: .dockerignore.
    4. 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.
    5. 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?).
    6. 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:.
    7. 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.

    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 / # nosec.

    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