123% di CVE segnalate in più al giorno nel 2026 rispetto all'anno scorso.

Supply chain

Che cos'è la dependency confusion?

La dependency confusion è un attacco in cui una build installa il pacchetto pubblico di un attaccante al posto del Suo pacchetto privato con lo stesso nome. Nessuno commette un errore di battitura. All'attaccante basta scoprire il nome di un pacchetto interno e pubblicarlo su un registry pubblico con un numero di versione alto: una build mal configurata fa il resto.

Aggiornato il

Come funziona un attacco di dependency confusion

  1. Individuazione di un nome interno. I nomi dei pacchetti privati trapelano attraverso codice pubblico, bundle JavaScript, messaggi di errore e manifest lasciati nei repository.
  2. Pubblicazione dello stesso nome. L'attaccante lo registra su npm, PyPI o un altro registry pubblico, con un numero di versione molto alto.
  3. Attesa di una build. Un package manager configurato per controllare sia il registry interno sia quello pubblico trova due candidati e preferisce la versione più alta.
  4. Esecuzione all'interno dell'azienda. Lo script di installazione del pacchetto viene eseguito sulla macchina di uno sviluppatore o su un runner CI, con accesso a tutto ciò che vi si trova.

La ricerca che ha dato il nome all'attacco

Nel febbraio 2021, il ricercatore di sicurezza Alex Birsan ha pubblicato la tecnica. L'aveva usata per eseguire codice all'interno di oltre 35 organizzazioni, tra cui Apple, Microsoft e PayPal, nell'ambito di programmi di bug bounty o con autorizzazione. Ha funzionato in tutti e tre i linguaggi che ha testato, e gli attaccanti hanno iniziato a copiarla entro pochi giorni dalla pubblicazione.

Perché succede

La causa principale è un package manager che tratta più registry alla pari. L'esempio classico è Python: --extra-index-url di pip aggiunge una seconda fonte accanto a PyPI, e pip può installare il pacchetto pubblico se ne trova uno con lo stesso nome.

# Unsafe for private packages: both indexes are candidates
pip install --extra-index-url https://pypi.internal.example/simple my-internal-lib

# Safer: one index you control, which proxies public packages
pip install --index-url https://pypi.internal.example/simple my-internal-lib

npm ha lo stesso problema con i nomi interni senza scope, mentre uno scope legato al Suo registry lo evita.

# .npmrc: everything under @acme comes only from your registry
@acme:registry=https://npm.internal.example/

Come prevenire la dependency confusion

  • Usi un'unica fonte di verità. Indirizzi le build verso un solo registry interno che fa da proxy per i pacchetti pubblici e lo configuri in modo che i nomi interni non vengano mai risolti pubblicamente.
  • Usi scope o namespace. Si assicuri la proprietà di uno scope come @acme sul registry pubblico e lo associ a quello privato.
  • Riservi i Suoi nomi. Registri i nomi dei pacchetti interni sui registry pubblici, così che nessun altro possa farlo.
  • Blocchi e verifichi. Esegua il commit di un lockfile e usi il controllo degli hash, come --require-hashes di pip, così che un pacchetto diverso faccia fallire l'installazione. Veda che cosa fa e che cosa non fa un lockfile.
  • Limiti dove possono connettersi le build. Se una build può raggiungere solo il Suo registry, non può affatto scaricare il pacchetto dell'attaccante. Veda policy di egress per GitHub Actions.
  • Controlli ciò che trapela. Cerchi i nomi dei Suoi pacchetti interni nel codice pubblico e nei bundle client.

Dependency confusion e typosquatting

Il typosquatting si basa su una persona che digita male il nome di un pacchetto pubblico. La dependency confusion usa il nome esatto di un pacchetto privato e si basa sul modo in cui è configurata la build. Entrambi portano allo stesso risultato: codice dell'attaccante in esecuzione nella Sua build. Veda che cos'è un attacco alla supply chain per capire come si collocano rispetto agli altri attacchi.

Come capire se è stato colpito

Cerchi i nomi di pacchetti interni che sono stati risolti da un registry pubblico, o versioni che non esistono nel Suo registry interno. Partendo solo da un lockfile è difficile, perché la domanda è da dove è arrivato davvero un pacchetto durante la build.

Come aiuta CRACI

CRACI lavora nel punto in cui il pacchetto viene scaricato. Come Suo runner GitHub Actions, applica una policy di egress con fonti tipizzate per i registry, così una build può essere limitata ai registry che Lei consente. Registra inoltre in una SBOM ogni pacchetto scaricato da ciascun job, così Lei può vedere che cosa è entrato in una build. CRACI non rileva che un pacchetto è malevolo, quindi mantenga la configurazione dei Suoi registry come prima linea di difesa. Veda le best practice per la sicurezza della software supply chain.

Dependency confusion: domande frequenti

Che cos'è un attacco di dependency confusion?

Un attacco in cui un pacchetto pubblico con lo stesso nome di uno privato viene installato per errore, perché il package manager controlla entrambi i registry e preferisce la versione più alta.

In che cosa la dependency confusion è diversa dal typosquatting?

Il typosquatting si basa su qualcuno che digita male il nome di un pacchetto pubblico. La dependency confusion usa il nome esatto di un pacchetto privato e si basa su una configurazione di build che controlla i registry pubblici.

Come si previene la dependency confusion?

Con un unico registry interno, nomi di pacchetti con scope, lockfile con controllo degli hash e regole che limitano i registry raggiungibili dalle build. Aiuta anche riservare pubblicamente i nomi interni.

--extra-index-url è sicuro?

Non per i pacchetti privati. Rende candidati entrambi gli indici, quindi può essere installato un pacchetto pubblico con lo stesso nome. Usi --index-url con un solo indice sotto il Suo controllo.

Chi ha scoperto la dependency confusion?

Il ricercatore di sicurezza Alex Birsan ha pubblicato la tecnica nel febbraio 2021, dopo averla usata contro oltre 35 organizzazioni nell'ambito di programmi di bug bounty o con autorizzazione.

Limiti da dove possono scaricare le Sue build

Consenta solo i registry di cui un job GitHub Actions ha bisogno e veda ogni pacchetto che ha scaricato.

Prenota una demo