Questo pezzo è per chi lascia scrivere codice a un agente o a un assistente e poi installa le dipendenze che propone. Fa parte dell'hub Vibe coding e si affianca alla checklist per mettere in produzione un sito vibe-coded.
In breve: un modello che scrive codice a volte importa pacchetti che non esistono. Se il nome inventato è sempre lo stesso, qualcuno può registrarlo e metterci dentro codice malevolo. Si chiama slopsquatting. Uno studio presentato a USENIX Security 2025 ha trovato che quasi un pacchetto su cinque suggerito dai modelli testati non esisteva. La difesa non è smettere di usare l'AI: è controllare ogni dipendenza nuova prima di installarla, e lasciare che npm blocchi il resto.
Cos'è lo slopsquatting
Slopsquatting è la registrazione, su un registry pubblico come npm o PyPI, di un nome di pacchetto che i modelli linguistici inventano. Chi lo registra spera che qualcuno copi il comando suggerito dall'AI e installi la versione malevola senza accorgersene.
È un parente del typosquatting. Lì si sfrutta un errore di battitura umano. Qui si sfrutta un errore del modello. Il nome è nato nell'aprile 2025 da una conversazione tra Seth Larson, della Python Software Foundation, e Andrew Nesbitt, come racconta lo stesso Nesbitt nel suo blog. L'attacco in sé era già stato documentato nel 2023 da Lasso Security.
Il meccanismo è semplice. Il modello non consulta il registry quando scrive un import. Predice il nome più plausibile. A volte il nome plausibile esiste, a volte no.
Cosa ha misurato lo studio USENIX 2025
Il riferimento è We Have a Package for You! di Spracklen e colleghi, presentato a USENIX Security 2025. Hanno usato 16 modelli per generare 576.000 campioni di codice in Python e JavaScript. Poi hanno controllato ogni pacchetto citato contro PyPI e npm.
I numeri principali, tutti dal paper:
Dato | Valore |
|---|---|
Pacchetti generati in totale | 2,23 milioni |
Pacchetti inesistenti | 440.445, cioè il 19,7% |
Nomi inventati unici | 205.474 |
Media modelli commerciali | almeno 5,2% |
Media modelli open source | 21,7% |
Nomi inventati ripetuti in tutte e 10 le richieste uguali | 43% |
Nomi inventati generati da un solo modello | 81% |
Il codice JavaScript ha prodotto più nomi inesistenti del codice Python. E l'8,7% dei nomi Python inventati corrispondeva a pacchetti JavaScript reali: il modello confonde gli ecosistemi.
Il problema è la ripetibilità
Un errore casuale sarebbe solo fastidioso. Il dato che rende l'attacco praticabile è un altro: ripetendo la stessa richiesta 10 volte, il 43% dei pacchetti inventati è tornato tutte e 10 le volte. Nel 58% dei casi è tornato più di una volta.
Questo vuol dire che un nome inventato non è rumore. È prevedibile. Chi vuole attaccare può fare le stesse domande ai modelli, raccogliere i nomi che non esistono e registrare quelli che ricorrono di più. Poi aspetta.
Non aspettarti che basti cambiare le impostazioni del modello. Gli autori notano che, proprio perché si ripetono, i nomi inventati uscirebbero anche con una decodifica più deterministica.
Il controllo in un minuto, prima di npm install
La regola è una: nessuna dipendenza nuova entra nel progetto senza un controllo, chiunque l'abbia proposta. Il controllo minimo si fa dal terminale con npm view, che legge i metadati dal registry senza installare niente.
# Esiste? Se il pacchetto non c'è, npm risponde con un errore 404
npm view nome-pacchetto name version
# Quando è nato e quando è stato aggiornato l'ultima volta
npm view nome-pacchetto time.created time.modified
# Da dove viene il codice e chi lo pubblica
npm view nome-pacchetto repository.url homepage maintainers
# Quante dipendenze si porta dietro
npm view nome-pacchetto dependenciesCosa guardare nella risposta:
- Non esiste: il modello l'ha inventato. Non provare varianti del nome a caso. Chiedi all'agente cosa doveva fare quel pacchetto e cerca tu l'alternativa reale.
- Esiste ma è nato da pochi giorni: è il segnale più importante. Un nome inventato e poi registrato ha per forza una storia cortissima.
- Nessun repository o un repository vuoto: il codice pubblicato non è verificabile.
- Un nome quasi uguale a una libreria famosa: potrebbe essere typosquatting classico. Confronta con la pagina della libreria che conosci.
Per Python vale lo stesso ragionamento. Apri la pagina del progetto su PyPI prima di installare e guarda data della prima release, link al sorgente e maintainer.
Cosa fa già npm per te
La CLI di npm ha tre difese che vale la pena conoscere. Le trovi nella documentazione della configurazione della versione 12, l'ultima al momento in cui scrivo.
Nella CLI 12 gli script di installazione delle dipendenze sono bloccati di default. Secondo la documentazione di npm approve-scripts, preinstall, install e postinstall delle dipendenze non partono se il pacchetto non è nel campo allowScripts del package.json. A fine installazione npm elenca quelli saltati. Approvali uno per uno, non tutti insieme. Attenzione: questo ferma il codice eseguito durante l'installazione, non quello che il pacchetto esegue quando lo importi.
Puoi rifiutare le versioni troppo giovani. L'opzione min-release-age fa installare solo versioni pubblicate da più di un certo numero di giorni. Se non ce n'è nessuna, il comando fallisce. Contro un nome appena registrato è un filtro molto efficace.
Il lockfile decide, non l'agente. In CI usa npm ci: installa esattamente quello che c'è in package-lock.json e si ferma con un errore se non corrisponde al package.json. Ogni dipendenza nuova passa quindi da un diff che qualcuno vede. Con npm audit signatures verifichi anche firme del registry e attestazioni di provenienza dei pacchetti scaricati.
# .npmrc del progetto
# niente versioni pubblicate negli ultimi 7 giorni
min-release-age=7Il valore di 7 giorni è un esempio, non una soglia ufficiale. Il costo è reale: una patch di sicurezza appena uscita arriva con ritardo, e npm lo segnala quando blocca un audit fix.
Per Python l'equivalente del lockfile rigido è la modalità hash-checking di pip: con --require-hashes ogni pacchetto deve combaciare con l'hash scritto nel requirements.txt.
Dillo anche all'agente
Il paper ha provato anche a ridurre il problema alla fonte. Dare al modello informazioni esterne affidabili e fargli ricontrollare i pacchetti che ha proposto ha ridotto i nomi inventati. Il fine-tuning li ha ridotti a sua volta, ma ha peggiorato la qualità del codice.
Nella pratica di tutti i giorni l'equivalente è scrivere le regole nel file di contesto che l'agente legge davvero, come ho spiegato nel pezzo su AGENTS.md, CLAUDE.md e le regole di Cursor. Tre righe bastano:
- Non aggiungere dipendenze senza dirlo esplicitamente nel riepilogo.
- Per ogni dipendenza nuova, indica il link al repository e il motivo.
- Preferisci la libreria standard o una dipendenza già presente nel progetto.
Non è una garanzia. Il modello può comunque sbagliare il nome. Ma rende la dipendenza nuova visibile, e quello che è visibile si controlla. È lo stesso motivo per cui conviene diffidare dello stack di default proposto dall'AI: il modello sceglie ciò che ha visto spesso, non ciò che hai verificato.
Cosa conviene fare adesso
- Aggiorna npm alla versione 12 e controlla che il progetto abbia un campo
allowScriptsgestito connpm approve-scripts. - Aggiungi
min-release-ageal.npmrcdel progetto, con una soglia che ti sembra sostenibile. - In CI installa solo con
npm ci, mai connpm install. - Prima di accettare una dipendenza nuova proposta da un agente, esegui
npm viewe guarda data di creazione e repository. - Scrivi nel file di contesto dell'agente che le dipendenze nuove vanno dichiarate.
- Se un nome non esiste, non cercare di indovinare quello giusto: torna al problema e scegli tu la libreria.
Prima di andare online, ripassa la checklist per i siti vibe-coded: le dipendenze sono solo uno dei punti.
Domande frequenti
01Qual è la differenza tra slopsquatting e typosquatting?
Il typosquatting registra nomi simili a librerie famose e sfrutta gli errori di battitura delle persone. Lo slopsquatting registra nomi che i modelli inventano e sfrutta la fiducia di chi copia il codice generato. Il risultato è lo stesso: installi codice che non avevi scelto.
02Basta usare un modello commerciale per stare tranquilli?
No. Nello studio USENIX 2025 i modelli commerciali hanno inventato meno pacchetti degli open source, ma la media resta di almeno il 5,2%. Anche una dipendenza su venti va controllata.
03npm blocca già i pacchetti malevoli?
Blocca di default gli script di installazione delle dipendenze non approvate, e offre min-release-age e la verifica delle firme. Non sa però se un pacchetto con un nome plausibile fa quello che promette. Quel controllo resta tuo.



