Vai al contenuto
Supply chain PHP

Supply chain PHP: scansione di 6.000+ advisory ogni notte

Incolla un composer.json o un composer.lock e ottieni in trenta secondi un audit security-first del manifest: CVE attive nelle versioni installate (con CVSS vector e CWE ID), pacchetti abbandonati con suggerimento del sostituto, framework end-of-life con data di fine security support, audit del vincolo PHP, rilevamento di constraint wildcard, dipendenze su dev branch, repository non Packagist, plugin Composer abilitati. Dataset di 6.000+ advisory ricompilato ogni notte da Packagist Security API, OSV.dev e endoflife.date. L'analisi gira interamente nel browser: il tuo manifest non lascia mai la pagina.

Trascina qui un composer.json o composer.lock, oppure clicca per selezionare un file (max 5 MB)

Come usare l'audit

  1. 1

    Recupera composer.json o composer.lock

    Entrambi i file vivono nella radice del progetto PHP, accanto a vendor/. composer.json dichiara le dipendenze e i vincoli di versione (es. "laravel/framework": "^11.0"): è committato in git e visibile sul repository (GitHub, GitLab, Bitbucket). composer.lock è generato da composer install/update e contiene le versioni esatte risolte (es. 11.5.0) più gli hash di integrita: anch'esso è committato in git per garantire build deterministiche fra dev e production. Per un audit accurato preferisci il composer.lock: il manifest dice cosa è ammesso, il lock dice cosa è stato installato davvero.

  2. 2

    Incolla nel tool

    Il tool fa auto-detect del tipo: la presenza di un array top-level packages identifica il lock, la presenza di un oggetto require con vincoli stringa identifica il json. Il parsing JSON è strict: errori di sintassi falliscono con messaggio diagnostico esplicito. L'input non lascia il browser: nessuna richiesta di rete porta con sé il tuo manifest, l'analisi gira interamente in JavaScript locale contro un dataset statico precaricato dal sito.

  3. 3

    Leggi il report

    Output a due livelli. Statistiche: numero pacchetti totali, breakdown require / require-dev, vincolo PHP, estensioni richieste. Findings ordinati per severity (critical, high, medium, low, info): per ogni rilievo trovi pacchetto coinvolto, motivazione, riferimento al CVE pubblico (cve.org) o al GitHub Security Advisory (GHSA), CVSS vector quando presente, lista CWE associate, constraint vulnerabili e versione installata, suggerimento di remediation. In alto: punteggio aggregato 0-100 (verde sopra 80, giallo 50-80, rosso sotto 50).

  4. 4

    Esegui poi l'audit reale (CLI)

    Il triage statico nel browser ti dà la fotografia oggi. Per integrare in pipeline e bloccare regressioni future: composer audit da terminale (comando ufficiale dal Composer 2.4, settembre 2022) confronta i pacchetti installati con il database CVE FriendsOfPHP. composer require --dev roave/security-advisories:dev-latest aggiunge un meta-pacchetto che blocca l'installazione di pacchetti con CVE noti (zero overhead a runtime, solo conflict declarations). Best practice: composer audit --abandoned=report dentro il job di test della tua CI/CD, exit code != 0 se ci sono CVE attive.

Vulnerabilità note, EOL, abbandonati: i tre rischi reali della supply chain PHP

Le applicazioni PHP non muoiono di vecchiaia, muoiono di manutenzione mancata. In ogni progetto Composer non curato accadono tre cose in silenzio: nuove CVE vengono pubblicate sulle versioni effettivamente installate, autori smettono di mantenere librerie e marcano i pacchetti come abandoned, branch maggiori di framework escono dal security support. Dopo diciotto-ventiquattro mesi di immobilità, l'applicazione è formalmente funzionante ma esposta a vulnerabilità note e patchate da tempo nelle versioni nuove. Questo tool fa emergere quello stato in trenta secondi a partire dal solo manifest.

Cosa controlla l'audit, in concreto. Tre fonti distinte alimentano il triage. (1) Vulnerabilità note (CVE): l'API Packagist Security Advisory aggrega FriendsOfPHP/security-advisories e GitHub Advisory DB; OSV.dev (Open Source Vulnerabilities, gestito da Google) arricchisce ogni advisory con CVSS v3 vector e CWE ID. Coverage: 6.000+ advisory su 1.000+ pacchetti Composer. (2) End-of-life (EOL): endoflife.date pubblica i cicli release dei framework principali con data di fine security support. Pacchetti monitorati: PHP, Laravel (e illuminate/*), Symfony (e ogni symfony/*), Composer stesso, Guzzle, Twig, CakePHP, Drupal, GrumPHP. (3) Abandoned: il flag abandoned di Packagist viene letto per l'unione di tutti i pacchetti citati nelle advisory e dei top 2.000 pacchetti popolari, con cache TTL di 7 giorni. Risultato: 210+ pacchetti effettivamente abbandonati nel dataset.

Differenza fra audit del lock e audit del json. Il composer.lock contiene le versioni esatte risolte: il matcher fa lookup esatto contro l'intervallo affected dell'advisory (es. >=9.0.0,<9.5.6). Il composer.json contiene solo i constraint dichiarati (es. ^9.0): il matcher esegue intersezione fra il constraint utente e l'intervallo affected, segnalando se esiste almeno una versione installabile vulnerabile. Per audit rigorosi usa il lock. Il json è utile per stabilire se il vincolo permetterebbe di scaricare versioni vulnerabili anche con un nuovo composer install domani: lo flagga il triage, ma la verità è in produzione.

Il matcher di constraint è preciso. Non si limita al confronto major: implementa il caret ^X.Y.Z con la regola eccezione per major-zero (^0.5.0 = >=0.5.0 <0.6.0, ^0.0.5 = >=0.0.5 <0.0.6), il tilde ~X.Y, il wildcard X.Y.*, l'hyphen range 1.0 - 2.0, gli operatori >= <= > < =, l'OR || e l'AND comma-or-whitespace, le stability suffix -dev -alpha -beta -RC con priorità lessicografica. La normalizzazione è in DNF (disjunctive normal form) di intervalli e l'intersezione fra constraint è pairwise overlap: stessa semantica di composer/semver PHP, in JS vanilla, senza dipendenze.

Privacy operativa. Il composer.lock rivela la struttura completa di un progetto, le sue dipendenze transitive e gli eventuali pacchetti privati con riferimenti a repository VCS interni. Caricarlo su un servizio terzo per analisi preliminari non è una buona idea, anche con TLS: ogni servizio terzo è un vettore di leak per la mappa delle tue dipendenze. Qui non parte nessuna richiesta con i dati del manifest. Il dataset (16 shard advisory + 1 file EOL + 1 file abandoned) viene scaricato dal browser una sola volta al primo utilizzo e cachato in localStorage per le sessioni successive (invalidazione automatica via SHA-256 sui file pubblici). Audit, parsing e matching: tutto in locale.

Quando il triage statico è il livello giusto. Casi tipici. (a) Review preliminare di un progetto legacy senza accesso al filesystem: il cliente ti incolla il manifest in mail e vuole una valutazione in trenta secondi. (b) Pre-engagement audit per stimare lo sforzo di un eventuale incarico di adeguamento prima di firmare il preventivo. (c) Screen iniziale prima di un assessment cyber serio: definisci la lista dei high/critical da approfondire con esercizio di exploitability assessment, mappatura dei vettori applicabili, verifica della reachability dei codepath. (d) Self-check periodico per il proprietario dell'applicazione che vuole sapere se chi mantiene il codice sta facendo il suo lavoro.

Limite di scope. Il tool segnala CVE pubblicate, EOL noti, abbandoni dichiarati. Non sostituisce un Software Composition Analysis enterprise (Snyk, Mend, Sonatype): non controlla licenze, non genera SBOM CycloneDX, non analizza vulnerabilità di codice non-Composer (binari di sistema, script Node, container base image). Non sostituisce composer audit CLI integrato in pipeline. Non sostituisce un assessment manuale che valuti sfruttabilità reale dei vettori, presenza dei codepath nelle versioni, mitigazioni applicate a livello di hardening. È un triage e si propone come tale.

Cosa controlla esattamente

Il dataset è strutturato in tre componenti indipendenti, tutti pubblicati come file statici sotto /tools/resources/data/composer-audit/, ricompilati ogni notte da un job cron e versionati per SHA-256 nell'index.json.

Advisory (6.000+ in 1.000+ pacchetti). Sorgente primaria: Packagist Security Advisory API, che aggrega FriendsOfPHP/security-advisories (database YAML collaborativo) e i GitHub Security Advisories per pacchetti Composer. Sorgente di arricchimento: OSV.dev, dump Packagist completo, da cui estrarre per ogni advisory il CVSS v3 vector e gli identificatori CWE. Per ogni rilievo: id Packagist, cve, ghsa, severity dichiarata, CVSS, lista CWE, constraint affected (es. >=5.4.0,<5.4.50|>=6.0.0,<6.4.18|>=7.0.0,<7.1.11), data di reporting. Il payload viene shardato in 16 file per il primo nibble esadecimale di SHA-1 sul nome pacchetto: il browser carica solo i shard dei pacchetti effettivamente presenti nel manifest, non l'intero dataset.

End-of-life (9 prodotti, 133 cicli). Sorgente: endoflife.date via API /api/{product}.json. Per ogni ciclo: data di fine security support, flag LTS, latest patch release. Il client calcola lo status confrontando eol_date con today: eol se passato, soon-eol se entro 180 giorni, lts/current altrimenti. Pacchetti monitorati: PHP (vincolo del manifest), laravel/framework e tutti gli illuminate/*, symfony/symfony e ogni symfony/* standalone, composer/composer, guzzlehttp/guzzle, twig/twig, cakephp/cakephp, drupal/core, phpro/grumphp. Endoflife.date copre solo framework e tool con cicli pubblici: librerie singole come PHPUnit, Doctrine, Monolog, Flysystem, PHPStan, Carbon non hanno EOL pubblicato, sono coperte da CVE e abandoned.

Abandoned (210+ effettivamente abbandonati su 2.800 controllati). Strategia di copertura: union(A,B) dove A è l'insieme dei pacchetti citati nelle advisory (~1.000) e B è la lista dei top 2.000 pacchetti Packagist per popolarità. Per ogni nome: GET https://packagist.org/packages/{vendor}/{name}.json e lettura del campo abandoned (booleano true oppure stringa con il nome del sostituto suggerito). Cache su disco con TTL di 7 giorni per evitare re-fetch inutili a regime: a regime ogni esecuzione cron costa 30 secondi anziché i 4 minuti del primo bootstrap. Il client riceve solo i pacchetti effettivamente abandoned, non la lista completa dei controllati.

Atomicità delle pubblicazioni. Il job cron applica una scrittura atomica multifile: tutti i nuovi shard vengono scritti su file temporanei, rinominati uno per uno, e l'index.json con i nuovi SHA-256 è l'ultimo file rinominato. Se il processo muore a metà, i client continuano a leggere il dataset precedente tramite l'index.json non ancora aggiornato. Mai dataset parziale, mai mismatch fra index e shard. Se anche solo una delle tre fonti (Packagist, OSV, endoflife) fallisce, il job aborta senza pubblicare: meglio dataset vecchio di un giorno che dataset incompleto.

Come si legge un report

Punteggio aggregato 0-100. Calcolato come 100 - somma(severity_weights), dove i pesi sono: critical 30, high 15, medium 7, low 3, info 1. Lettura: 80-100 verde (postura supply chain ragionevole), 50-79 giallo (interventi pianificabili nelle prossime sprint), 0-49 rosso (debito tecnico significativo, alcuni interventi richiedono mitigazione immediata). Il punteggio non è una metrica di qualità del software in generale: misura solo la salute del manifest dal punto di vista di vulnerabilità, EOL e abbandono.

Severity dei finding. critical: vulnerabilità con CVSS >= 9.0 oppure severity Packagist critical, tipicamente RCE non autenticato, SQL injection diretta, deserializzazione insicura. high: CVSS 7.0-8.9 oppure severity high, oppure pacchetto EOL con CVE storica, oppure pacchetto abbandonato in produzione. medium: CVSS 4.0-6.9, vincolo PHP prossimo a EOL, dipendenze su dev branch. low: CVSS 1.0-3.9, vincolo PHP non specificato, repository non Packagist con type basso rischio (composer mirror, github). info: raccomandazioni operative (roave/security-advisories non installato, plugin Composer abilitati, repository VCS custom). Le finding sono ordinate dalla più grave alla meno grave dentro il blocco risultati.

Cosa fare in concreto, per priorità. (1) Per ogni critical: aggiornare immediatamente alla versione fixed indicata nel CVE record, oppure documentare per iscritto perché il vettore non è applicabile al codepath specifico (es. funzionalità non utilizzata, mitigazione applicata altrove). Non rimandare. (2) Per ogni high: pianificare upgrade entro la sprint corrente. Se il pacchetto è abbandonato, sostituire con il replacement suggerito o con un fork mantenuto. Se il framework è EOL, valutare il costo di upgrade alla branch corrente o LTS. (3) Per medium e low: backlog di hardening trimestrale, refactor incrementale del manifest verso vincoli stringenti (^X.Y minimo, mai *), rimozione di dipendenze su dev branch in favore di tag stabili. (4) Per info: aggiungere roave/security-advisories:dev-latest come dev dependency, eseguire composer audit in CI/CD, audit periodico dei plugin Composer abilitati con allow-plugins.

Format del finding CVE. Ogni rilievo CVE riporta versione installata, identificatori (CVE, GHSA), CVSS vector quando disponibile, lista CWE, constraint affected esatto. Il link nel campo Riferimenti punta a CVE Record (cve.org) o GitHub Advisory: lì trovi descrizione tecnica, exploit pubblici se documentati, versione fixed esatta, e il commit di patch upstream. Da girare al team con il messaggio operativo: aggiornare a versione fixed entro X giorni, oppure produrre un'analisi scritta della reachability del vettore nel codice applicativo.

Sorgenti dati e pacchetti monitorati

Il tool consuma un dataset statico ricompilato giornalmente da shared/cron/build_composer_audit_db.php. Tre fonti distinte alimentano il triage:

  • Advisory (Packagist Security API + OSV.dev): 6.000+ advisory su 1.000+ pacchetti Composer, arricchite con CVSS vector e CWE ID dal database OSV. Coverage indipendente dalla popolarità del pacchetto.
  • EOL (endoflife.date): framework e tool con cicli release pubblici. Pacchetti monitorati: php, laravel/framework (e illuminate/*), symfony/symfony (e ogni symfony/*), composer/composer, guzzlehttp/guzzle, twig/twig, cakephp/cakephp, drupal/core, phpro/grumphp. Per ogni branch: data di fine security support, status (current / lts / soon-eol / eol).
  • Abandoned (Packagist): campo abandoned letto da Packagist per l'unione di (a) tutti i pacchetti citati nelle advisory e (b) i top 2.000 pacchetti Composer per popolarità. ~2.800 pacchetti unici controllati per ciclo, cache TTL 7 giorni.

Librerie non coperte da EOL (PHPUnit, Doctrine, Monolog, Flysystem, PHPStan, Carbon, eccetera) restano comunque monitorate per CVE e abbandono: endoflife.date traccia solo framework/CMS, le librerie Composer non hanno cicli EOL pubblici equivalenti.

Glossario

Termini tecnici usati in questa pagina, spiegati in due righe.

composer.json #
File manifest del progetto PHP. Dichiara nome, autore, dipendenze (require, require-dev), constraint di versione (es. ^11.0), autoload PSR-4. Committato in git, è il documento autorevole su cosa il progetto dichiara di voler installare.
composer.lock #
File auto-generato da composer install/update. Contiene le versioni esatte risolte di ogni pacchetto + content-hash + timestamp. Garantisce build deterministica fra dev e production. Committato in git (best practice). Per audit di sicurezza precisi è la fonte autoritativa: il manifest dice cosa è ammesso, il lock dice cosa è installato davvero.
Constraint di versione Composer #
Sintassi per dichiarare quali versioni di una dipendenza sono accettabili. ^1.2 = SemVer compatible (>=1.2 <2.0, eccezione per major 0). ~1.2.3 = patch-level (>=1.2.3 <1.3.0). 1.2.* = wildcard. >=1.2,<1.5 = AND di operatori. ^1.0 || ^2.0 = OR di range. 1.0 - 2.0 = hyphen range. Best practice: ^X.Y per dipendenze stabili, ~X.Y.Z per dipendenze conservative dove preferisci solo patch.
CVE (Common Vulnerabilities and Exposures) #
Identificatore univoco di una vulnerabilità pubblica nel formato CVE-YYYY-NNNN. Assegnato dalla CVE Numbering Authority (CNA) competente. Database autoritativo: cve.org. Ogni CVE rilevante per ecosistema Composer ha una corrispondenza in Packagist Security e/o GitHub Advisory.
CVSS (Common Vulnerability Scoring System) #
Sistema standard per scoring di severity di una CVE. Versione corrente: 3.1 (4.0 in adozione progressiva). Output: vector string (es. CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) e base score 0.0-10.0. Severity bands: 0.1-3.9 low, 4.0-6.9 medium, 7.0-8.9 high, 9.0-10.0 critical.
CWE (Common Weakness Enumeration) #
Tassonomia delle classi di vulnerabilità software. Identificatori nel formato CWE-NNN (es. CWE-79 Cross-Site Scripting, CWE-89 SQL Injection, CWE-502 Deserialization of Untrusted Data, CWE-200 Information Disclosure). Una CVE può avere più CWE associate. Utile per pattern matching durante review e per training del team.
GHSA (GitHub Security Advisory) #
Identificatore di security advisory nativo GitHub, formato GHSA-xxxx-xxxx-xxxx. GitHub mantiene un database parallelo a CVE con triage spesso più rapido per ecosistemi open source. Ogni GHSA può corrispondere a un CVE pubblicato (mappatura esposta nel campo cve dell'advisory).
PSA (Packagist Security Advisory) #
Identificatore Packagist nel formato PKSA-xxxx-xxxx-xxxx. Packagist aggrega FriendsOfPHP/security-advisories e GHSA pertinenti all'ecosistema Composer in un endpoint unificato consultabile via API.
EOL (End Of Life) #
Data oltre la quale un pacchetto o framework non riceve più security update. Mantenere componenti EOL in production è un rischio: vulnerabilità nuove non vengono patchate sulla branch e l'unica strada è l'upgrade. In scope NIS2 (art. 21 c.2 lett. g) è esplicitamente segnalato come 'igiene cyber inadeguata'.
LTS (Long Term Support) #
Branch di un framework o linguaggio che riceve security update per un periodo esteso (tipicamente 2-5 anni) anche dopo il rilascio della versione successiva. Esempi: Laravel LTS storico (5.5, 6.x), Symfony LTS (4.4, 5.4, 6.4), PHP non ha LTS formale ma ogni minor riceve security update per circa 2 anni.
Abandoned #
Stato dichiarato dal maintainer in composer.json con il campo abandoned (boolean true oppure stringa con il nome del replacement suggerito). Packagist espone questo flag nel JSON pubblico del pacchetto. Da non confondere con deprecated: un pacchetto deprecated è ancora maintained ma sostituito da una versione successiva, un pacchetto abandoned è dichiarato fuori manutenzione dal suo autore.
FriendsOfPHP/security-advisories #
Database open source collaborativo di security advisory per pacchetti Composer. Aggiornato giornalmente, formato YAML, repository su GitHub. È la base storica del meta-pacchetto roave/security-advisories e dell'API Packagist Security Advisory.
OSV.dev #
Open Source Vulnerabilities, database mantenuto da Google. Schema OSV unificato, dump bulk per ecosistema (Packagist, npm, PyPI, Go, Maven, ecc.). Per ogni vulnerabilità: aliasing fra CVE/GHSA, severity CVSS v3, CWE ID, range affected per ogni package version. Sorgente di arricchimento per il dataset di questo tool.
endoflife.date #
Database open source dei cicli release di linguaggi, framework, runtime e tool. API JSON pubblica via /api/{product}.json. Per ogni ciclo: data di rilascio, fine supporto attivo, fine security support, flag LTS, ultima patch release. Sorgente del dataset EOL di questo tool.
roave/security-advisories #
Meta-pacchetto Composer (no codice, solo conflict declarations) che blocca l'install di pacchetti con CVE noti. Pattern d'uso: composer require --dev roave/security-advisories:dev-latest. Zero overhead a runtime, zero impact sulle build dimensioni: i conflict si valutano solo al solve time del dependency manager.
composer audit #
Comando ufficiale Composer disponibile dalla 2.4 (settembre 2022). Confronta i pacchetti installati con il database CVE di Packagist Security e produce output testuale o JSON. Exit code != 0 se sono presenti CVE attive. Da integrare nei job di test in CI/CD per bloccare merge su PR che introducono regressioni di security.
Renovate / Dependabot #
Bot automatici (GitHub Dependabot nativo, Renovate Bot multi-platform) che monitorano dependencies e aprono PR di aggiornamento. Per PHP-Composer: supporto nativo, riconoscono security advisories e prioritizzano le PR di security separandole dagli update minor/patch ordinari.
Supply chain security #
Disciplina della sicurezza ICT focalizzata sulle dipendenze di terze parti: librerie open source, package registry, mirror, build runner, deploy artifact. Scope NIS2 (art. 21 c.2 lett. d) include esplicitamente la supply chain ICT come materia di gestione del rischio. Strumenti operativi: SBOM (Software Bill of Materials), signing dei deploy, monitoring CVE in continuo, policy di update con SLA.

Domande frequenti sul Composer audit

Sono il proprietario o il project manager di un'applicazione PHP, non sono uno sviluppatore. Mi serve davvero questo tool?
Sì, ed è anzi uno dei target. La logica del tool è scritta per essere leggibile senza conoscenza approfondita di PHP: per ogni finding ricevi severity (critica, alta, media, bassa, informativa), nome del pacchetto coinvolto, motivazione esplicita e link al CVE pubblico o all'advisory GitHub. Se il report restituisce più di tre o quattro finding di severity high o critical sulle dipendenze di produzione, hai un argomento concreto da portare al team di sviluppo per chiedere come e quando l'applicazione verrà aggiornata.
Dove trovo materialmente il composer.json o il composer.lock della mia applicazione?
Entrambi vivono nella radice del progetto, accanto alla cartella vendor/. Tre vie tipiche di reperimento. (1) Repository git: chiedi accesso al repository (GitHub, GitLab, Bitbucket) e li trovi in radice, sono file di testo committati. (2) Server di produzione: se hai accesso SSH alla macchina, sono in /var/www/<nome-progetto>/composer.json o simili. (3) Hosting condiviso: spesso accessibili via FTP/SFTP o pannello di controllo. In nessun caso questi file contengono dati sensibili dell'applicazione (utenti, password, transazioni): contengono solo la lista delle librerie e le loro versioni.
Il report mi segnala un pacchetto come EOL e il mio sviluppatore mi dice 'non è urgente'. Come rispondere?
EOL significa che il maintainer del pacchetto NON rilascia più security update sulla branch in uso. Le vulnerabilità nuove non vengono patchate per quella versione. Non è una stima soggettiva: è una data pubblica. La risposta corretta da uno sviluppatore competente è 'pianifico l'upgrade entro la data X' oppure 'il vettore non è applicabile al nostro scenario perché abbiamo Y, e lo documento per iscritto', non 'non è urgente'. In ambito NIS2 (art. 21 c.2 lett. g, recepita in Italia con il D.Lgs. 138/2024) tenere componenti EOL in produzione viene esplicitamente trattato come segnale di igiene cyber inadeguata.
Differenza fra un audit del lock e un audit del json?
Il composer.lock contiene le versioni esatte risolte: il tool sa che hai installato esattamente 9.5.10 e può dirti se quella versione specifica è affected da una CVE. Il composer.json contiene solo i constraint dichiarati (^9.0): il tool non conosce la versione effettiva, ma può dirti se il vincolo permetterebbe di installare versioni vulnerabili. Per audit precisi e di valore operativo immediato usa il lock; il json è utile per capire se un nuovo composer install domani potrebbe scaricare versioni affected o no.
Il tool segnala specifiche CVE per ogni pacchetto?
Sì. Il dataset alimentato da Packagist Security API + OSV.dev contiene 6.000+ advisory pubblicate con identificatore CVE quando assegnato, GitHub Security Advisory (GHSA), severity, CVSS vector v3 quando arricchito da OSV, lista CWE associata, constraint affected esatto. Per ogni match: link diretto al CVE Record o alla pagina GitHub Advisory. Il dataset è ricompilato ogni notte per restare allineato con le nuove pubblicazioni.
Il matching delle versioni è preciso o solo approssimativo?
Preciso, lato lock. Il modulo ComposerSemver implementa la stessa semantica di composer/semver PHP: caret, tilde, wildcard, hyphen range, OR/AND, stability suffix, eccezione major-zero. Sul lock fa lookup esatto (versione concreta vs intervallo affected). Sul json fa intersezione di intervalli normalizzati in DNF: la finding viene emessa quando esiste almeno una versione installabile coperta sia dal vincolo dichiarato sia dall'intervallo vulnerabile. Il modulo è validato da una suite di 44 fixture (eseguibile manualmente da console: ComposerSemver.runFixtures()).
Quanti pacchetti riesco a controllare in un audit? Performance?
Performance OK fino a 1.000 pacchetti in un singolo audit. Il tempo dominante è il fetch dei shard advisory (fino a 16 file da ~100 KB ciascuno, gzippati a ~25 KB). Con cache calda l'audit è istantaneo (parsing + matching su qualche centinaio di pacchetti = millisecondi). Per progetti enterprise con 1.000+ deps: composer audit CLI è più veloce e accurato (legge direttamente vendor/composer/installed.json). Il nostro tool è ottimizzato per progetti tipici fra 30 e 300 deps, l'80% dei progetti consulenza/PMI.
Cosa succede se carico un pacchetto sconosciuto al dataset?
Viene contato nelle statistiche generali ma non emette finding. Sconosciuto al dataset non significa pericoloso: la maggior parte dei pacchetti Composer è di nicchia o privata e non è mai stata oggetto di advisory pubblica, EOL pubblicato o flag abandoned. Per coverage più ampia su pacchetti di nicchia: composer audit CLI legge il database CVE FriendsOfPHP completo, e Snyk/Dependabot integrati nel repository monitorano in continuo.
Il vincolo PHP del progetto è <code>>=7.4</code>. Cosa segnala il tool?
Lo flagga come php_eol: il vincolo include PHP 7.4 (security support terminato 2022-11), 8.0 (terminato 2023-11), 8.1 (terminato 2025-12). Significa che composer install formalmente accetterebbe l'installazione su una macchina con PHP 7.4 anche se la realtà di production è 8.x. Best practice: >=8.2 minimo nel constraint, indipendentemente dalla versione di production attuale. Comunica intent + previene installazioni accidentali su VPS legacy + è un segnale di igiene cyber per audit esterni.
Symfony ha tanti componenti standalone (<code>symfony/console</code>, <code>symfony/yaml</code>, eccetera). Sono tutti coperti?
Sì. Il tool considera ogni pacchetto symfony/* con la stessa policy LTS della release principale (Symfony 5.4 LTS = symfony/console:5.4 LTS, eccetera). Il mapping è via prefisso symfony/ nel product_prefixes dell'eol.json. Stesso pattern per illuminate/* mappati al ciclo Laravel. Eccezioni rare (componenti con cicli leggermente diversi dalla release principale) non sono modellate per non introdurre falsi positivi su corner case marginali.
Il tool integra una libreria PHP/JS esterna a runtime?
No. JSON parse è nativo, il matcher di constraint è il modulo composer-semver.js scritto da zero, il fetch del dataset usa l'API fetch nativa, il sharding usa crypto.subtle.digest('SHA-1') nativo. Zero dipendenze, totale ~13 KB di JavaScript (3 KB minified gzip per il semver, 10 KB gzip per il GUI). Il dataset stesso è statico, ricompilato dal cron PHP server-side: il browser scarica solo i shard necessari per i pacchetti del manifest, non l'intero dataset.
Differenza fra abandoned, deprecated e EOL?
Abandoned: il maintainer ha esplicitamente marcato il pacchetto come abbandonato in composer.json (campo abandoned letto da Packagist). Deprecated: il pacchetto è ancora maintained ma sostituito da una versione successiva (es. league/flysystem 1.x deprecato in favor di 2.x). EOL: il maintainer non rilascia più security update sulla branch (es. Symfony 5.4 dopo novembre 2025). Tutti e tre richiedono pianificazione di migration; abandoned e EOL su rami di produzione sono i più urgenti.
Posso usare il tool sul composer.json di una libreria, non di un'applicazione?
Sì, funziona uguale. Le librerie tipicamente hanno meno pacchetti (10-30) e sono più conservative sulla retrocompatibilità. Findings tipici su libreria: vincolo PHP troppo permissivo (>=7.0 per supportare downstream legacy), version pinning di test framework ormai EOL, dipendenze su vecchi doctrine/cache abandoned. Audit utile prima di pubblicare una nuova major release o di chiudere lo scope di una versione long-term.
Come integro l'audit reale in CI/CD?
GitLab CI: composer audit --abandoned=report --format=json dentro il job di test, exit code != 0 fa fallire il merge. GitHub Actions: stesso comando, opzionalmente con action tj-actions/composer-audit. Pre-commit hook: composer audit dentro .husky/pre-commit oppure .git/hooks/pre-commit. Best practice: eseguire l'audit anche sui tag di release, non solo sulle PR, per catturare CVE pubblicate fra il merge e il deploy. Per blocco install di pacchetti vulnerabili: composer require --dev roave/security-advisories:dev-latest.
Il dataset è aggiornato in tempo reale?
Quasi: il cron lo ricompila ogni notte alle 03:00 UTC. Latency tipica fra pubblicazione di una nuova CVE su Packagist e visibilità nel tool: meno di 24 ore. Per latency zero serve composer audit CLI integrato in pipeline, che interroga l'API Packagist al momento dell'esecuzione. La scelta del rebuild giornaliero è un compromesso fra freschezza e costo di rete (il job fa ~2.800 chiamate Packagist a regime).
Privacy: il manifest che incollo viene salvato o tracciato?
No. Il tool gira interamente nel browser. L'unica richiesta di rete che parte è il GET dei file dataset statici, identici per tutti gli utenti, completamente anonimi. Il composer.json o composer.lock incollato non viene mai inviato a nessuna richiesta di rete, non viene salvato in localStorage, non viene tracciato in analytics. Si può verificare aprendo il pannello Network di DevTools durante l'audit: zero richieste outgoing con i dati del manifest.

La supply chain del tuo progetto PHP regge un audit serio?

Questo tool è un triage statico: rileva CVE pubblicate, EOL noti e abbandoni dichiarati visibili dal solo manifest. Una review professionale esamina la catena completa: inventario delle dipendenze (dirette e transitive), monitoring CVE in continuo via Dependabot o Renovate, policy di update con SLA per severity, hardening della pipeline CI/CD, signing dei deploy, scope NIS2 supply chain (art. 21 c.2 lett. d), exploitability assessment dei vettori sui codepath effettivamente raggiungibili. Se il triage di sopra ha mostrato una lista che non ti aspettavi, il problema esiste già: il prossimo passo è capire priorità reali, costi e tempi degli interventi. Lavoro su backend Laravel, Symfony e PHP custom da oltre 10 anni, con focus su applicazioni in produzione e adeguamenti normativi.

Audit supply chain PHP

Vuoi una stima realistica per il tuo progetto?

Wizard di 7 domande, 2 minuti, gratuito. Output: range di giorni-uomo, range di prezzo orientativo e raccomandazione di ingaggio. Tariffa di riferimento 300 euro al giorno. Pensato per progetti backend custom, integrazioni, audit di sicurezza o automazione AI.

Calcola il preventivo