GitLab CVE-2026-19478: una direttiva GraphQL non autenticata può cancellare i tuoi repo
La patch fuori programma di GitLab chiude CVE-2026-19478 (CVSS 9.4): una direttiva GraphQL non autenticata che può modificare o cancellare progetti pubblici e dati utente. Chi è esposto e come intervenire.
Lunedì 17 agosto 2026 GitLab ha pubblicato una patch fuori programma per un solo motivo: CVE-2026-19478, una falla critica che consente a un attaccante non autenticato di "modificare o cancellare da remoto progetti pubblici e dati utente tramite una direttiva GraphQL". Nessun login. Nessuna interazione dell'utente. GitLab.com e GitLab Dedicated giravano già sulla build corretta prima ancora dell'advisory — il che significa che tutto il peso ricade sulle installazioni self-managed, le istanze esposte su internet che stanno alla radice della supply chain software di quasi ogni organizzazione.
Il punteggio CVSS è 9.4. Il numero che conta di più è nascosto nella stringa del vettore.
Cos'è davvero CVE-2026-19478
GitLab ha pubblicato la forma del bug, non il meccanismo. Secondo l'advisory della patch, la falla "in certe condizioni potrebbe consentire a un utente non autenticato di modificare o cancellare da remoto progetti pubblici e dati utente tramite una direttiva GraphQL". Il dettaglio tecnico completo è sotto embargo per circa 90 giorni — la finestra di disclosure standard di GitLab — quindi le condizioni di sfruttamento diventeranno pubbliche intorno a metà novembre 2026. Chi difende non può aspettare fino ad allora.
Il vettore CVSS è CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H. Letto da sinistra a destra, la gravità non riguarda davvero il furto:
| Metrica | Valore | Cosa significa qui |
|---|---|---|
| Attack Vector | Network | Raggiungibile dall'interfaccia web esposta |
| Attack Complexity | Low | Nessuna condizione speciale da vincere |
| Privileges Required | None | Non autenticato |
| User Interaction | None | Nessuna vittima deve cliccare nulla |
| Confidentiality | Low | Pochi dati letti |
| Integrity | High | I dati possono essere modificati |
| Availability | High | I dati possono essere distrutti |
La confidenzialità è quella bassa. Integrità e disponibilità sono alte. Non è un bug da furto di dati — è un bug da sabotaggio. L'attaccante che lo sfrutta non esfiltra silenziosamente il tuo codice: lo altera o lo cancella del tutto, e il primo segnale che ricevi è un progetto che c'era e non c'è più.
Lo stesso rilascio ha chiuso anche CVE-2026-19650 (CVSS 7.1), un cross-site request forgery nel gestore delle query GraphQL multiplex che permetteva a un utente non autenticato di "eseguire mutation tramite richieste GET a causa di validazione impropria della richiesta". Due bug GraphQL in un unico rilascio d'emergenza non è una coincidenza — è un segnale su dove vive oggi la superficie d'attacco esposta di GitLab.
Perché "cancellare progetti pubblici" è peggio di una fuga di dati
I team di sicurezza sono addestrati a temere l'esfiltrazione. Un gruppo di double-extortion ruba i tuoi repository, minaccia di pubblicarli, e passi un brutto trimestre. È sopravvivibile perché il dato esiste ancora — ce l'hai tu, ne hanno una copia loro.
Gli attacchi a integrità e disponibilità su un server di source control sono una modalità di fallimento diversa. L'SCM è la radice di fiducia di tutto ciò che sta a valle: le pipeline CI/CD ci pescano dentro, le build degli artefatti sono definite lì, l'infrastructure-as-code vive lì. Un attore non autenticato che può modificare un progetto può:
- Infilare un commit malevolo in un repository pubblico da cui pescano migliaia di consumatori a valle.
- Riscrivere le definizioni di pipeline così che la build successiva spedisca una backdoor — la RCE pre-auth di TeamCity di cui abbiamo scritto questo mese è la stessa lezione dal lato CI della stessa pipeline.
- Cancellare storia, tag o interi progetti per coprire le tracce o per puro danno operativo.
"Davamo per scontato che il raggio d'azione di un bug GitLab fosse 'qualcuno legge il nostro codice privato'. Non avevamo un runbook per 'qualcuno ha cancellato il progetto pubblico su cui trecento clienti fanno la build'. Non è un problema di incident response. È un problema di ricostruzione da backup, e abbiamo scoperto che i backup dei metadati di progetto erano vecchi di tre giorni."
È questo il controfattuale su cui vale la pena fare war-gaming. Quasi tutti sanno ripristinare gli oggetti Git di un repository. Molti meno sanno ripristinare pulitamente lo stato GitLab attorno — issue, storia delle merge request, token, membership — a un punto valido noto, e ancora meno l'hanno mai testato.
I bug di GitLab vengono armati in fretta
Il motivo per trattare come urgente un CVE GitLab non ancora sfruttato è il tasso base. A gennaio 2024 GitLab divulgò CVE-2023-7028, una falla di account-takeover con CVSS 10.0 in cui un'email di reset password poteva essere inviata a un indirizzo controllato dall'attaccante. Poco appariscente — un errore logico di una riga nel flusso di reset. Nel giro di mesi era sotto sfruttamento attivo e la CISA l'ha aggiunta al catalogo Known Exploited Vulnerabilities. Le vittime erano, in stragrande maggioranza, istanze self-managed non aggiornate.
Lo schema si ripete perché GitLab self-managed ha un ritardo strutturale: la piattaforma SaaS riceve la fix al giorno zero, e la lunga coda di istanze on-prem si aggiorna in settimane o mesi. Gli attaccanti sanno che l'advisory è un colpo di pistola allo start. Per un bug non autenticato, raggiungibile in rete e a bassa complessità su una piattaforma diffusissima, la finestra tra "patch pubblicata" ed "exploit pubblico" è il tempo che serve a uno scanner per reverse-engineerizzare la fix — e i diff di GraphQL non sono difficili da leggere.
CVE-2026-19478 non ha exploit pubblici mentre scriviamo. È la buona notizia e la scadenza nella stessa frase.
Il problema delle direttive GraphQL
Le direttive sono la parte di GraphQL che quasi nessun team verifica. Sono i modificatori con prefisso @ — @skip, @include, @defer e quelle custom che uno schema definisce — che cambiano come una query viene risolta anziché cosa chiede. Poiché operano come uno strato trasversale sul grafo dei resolver, sono una sede ricorrente di bug di bypass dell'autorizzazione: se la logica della direttiva gira in un punto dove il contesto dell'utente autenticato non è quello che il resolver assume, una richiesta può finire per essere eseguita con l'autorità sbagliata.
Le direttive @defer e @stream, in particolare, spezzano una singola query in blocchi consegnati in modo incrementale. Quello spezzettamento è esattamente il tipo di giuntura nel flusso di controllo dove vivono gli errori del tipo "il controllo di auth è avvenuto, ma non su questo ramo". GitLab non ha confermato quale direttiva sia implicata in CVE-2026-19478, e non tireremo a indovinare in pubblico — ma la classe è ben compresa, e "mutation non autenticata raggiungibile tramite una direttiva" ci sta dentro in pieno. Il bug CSRF gemello che esegue mutation via GET punta allo stesso tema: operazioni che cambiano stato raggiungibili tramite percorsi di richiesta che non avrebbero mai dovuto trasportarle.
Se hai GraphQL da qualche parte nel tuo stack, questo è il promemoria per verificare che l'autorizzazione sia imposta nei resolver stessi, non in uno strato che una direttiva può aggirare.
Remediation
CVE-2026-19478 ha una fix pulita e un'esposizione facile da ragionare. Procedi in ordine.
1. Sono esposto?
Controlla la tua versione di GitLab — solo self-managed; GitLab.com e Dedicated sono già patchate.
# Sull'host GitLab
gitlab-rake gitlab:env:info | grep -i version
# oppure, da qualsiasi istanza
curl -s https://<tuo-gitlab>/api/v4/version # richiede un token
# oppure leggi il footer / la pagina di aiuto: /help
Esposte: GitLab CE ed EE dalla 18.2 fino alle linee 18.11 / 19.0 / 19.1 / 19.2 non patchate. Se sei su una release dalla 18.2 in poi al di sotto delle build corrette, sei esposto. Le istanze raggiungibili da internet sono la priorità; ma "solo interna" non è un'assunzione sicura per un bug non autenticato una volta che un attaccante ha un qualsiasi appiglio in rete.
2. Patch — versioni corrette esatte
Aggiorna alla release corretta più vicina sul tuo ramo, testuale dall'advisory:
- 19.2.4
- 19.1.6
- 19.0.8
- 18.11.11
Non esiste workaround di configurazione avallato da GitLab. La patch è la fix.
3. Non puoi patchare subito? Controlli compensativi
Guadagna tempo, non sostituire l'aggiornamento:
- Metti l'interfaccia web di GitLab dietro autenticazione al perimetro (VPN / allow-list su reverse-proxy) così che il traffico internet non autenticato non raggiunga affatto
/api/graphql. - Al WAF o al reverse proxy, blocca o limita fortemente le richieste
POSTeGETnon autenticate all'endpoint GraphQL — il CVE-2026-19650 gemello abusa di GET, quindi una regola solo-POST è insufficiente. - Disattiva la visibilità pubblica sui progetti che non puoi permetterti di perdere mentre patchi, riducendo i "progetti pubblici" che il bug prende di mira esplicitamente.
4. Caccia alla compromissione
Poiché il bug modifica o distrugge dati, l'evidenza sta nei log applicativi e di audit, non nella telemetria di esfiltrazione. Mappa su MITRE ATT&CK:
- T1190 — Exploit Public-Facing Application:
POST/GETanomale verso/api/graphqlda sessioni non autenticate, in particolare richieste che portano direttive su operazioni di mutation. - T1485 — Data Destruction / T1565 — Data Manipulation: cancellazione di progetti o repository e modifiche alle impostazioni senza un utente autenticato corrispondente nell'evento di audit. Rivedi gli audit event di GitLab e i log
application_json/production_jsonper attività di mutation non riconducibili a un attore reale. - T1195 — Supply Chain Compromise: commit inattesi, riscritture di tag o modifiche alla configurazione CI/CD su progetti pubblici. Diffa le definizioni di pipeline correnti contro una baseline valida nota.
Gli IOC saranno scarsi finché non esce il dettaglio tecnico — ed è proprio per questo che la detection comportamentale (una richiesta che cambia dati senza alcuna identità autenticata dietro) batte l'attesa di una firma.
5. Bonifica e verifica
Se trovi evidenza di manomissione:
- Ripristina i progetti e i metadati colpiti da un backup precedente alla prima attività GraphQL sospetta — e verifica che il ripristino copra davvero issue, storia delle MR e membership, non solo gli oggetti Git.
- Ruota tutto ciò che un attaccante con accesso in scrittura potrebbe aver visto o piantato: variabili CI/CD, deploy token, token di registrazione dei runner e qualsiasi segreto committato nei repo colpiti.
- Ri-verifica l'integrità dopo aver patchato, non prima — un'istanza non patchata può essere ri-manomessa nell'istante in cui finisci di ripulirla.
Dove entra Zero Hunt
La parte scomoda di CVE-2026-19478 è il tempismo. La patch c'è, l'exploit no — non ancora — e l'unica domanda che conta è se il tuo GitLab sia esposto adesso, sulla versione che sta davvero girando, dietro i controlli di rete che davvero hai. Un pentest trimestrale risponde a quella domanda per una versione che hai dismesso due mesi fa.
Il motore generativo a 10 agenti di Zero Hunt è costruito per rispondere in continuo. Le sue campagne innescate dai cambiamenti trattano un nuovo advisory come lo tratta un attaccante: come un colpo di pistola allo start. Quando un'istanza GitLab compare sul perimetro, o esce un advisory per software che usi, gli agenti Recon e Web fingerprintano la versione esposta e l'agente Exploit scrive una catena di validazione per-target — generata localmente, unica al tuo ambiente, non pescata da un PoC pubblico che ancora non esiste. Scopri se sei sfruttabile dalla tua stessa evidenza, non da una stima CVSS, e lo scopri nelle ore che contano invece che al prossimo audit.
Poiché è un bug di integrità e disponibilità, la seconda metà della risposta è probatoria. Ogni finding, ogni esposizione validata e ogni remediation viene mappata contro i 32 framework di compliance che Zero Hunt traccia e firmata ECDSA al momento della scrittura, così che quando un auditor — o un legale in un incidente — chiede "dimostrami che il tuo GitLab era patchato e pulito prima che chiudesse la finestra di disclosure", hai un record con chain-of-custody che dice esattamente quando, non uno screenshot. Per un bug il cui pericolo è che i dati possano essere silenziosamente cambiati o cancellati, un log a prova di manomissione di come apparivano i tuoi sistemi, e quando, non è un vezzo di compliance. È la baseline forense che vorresti aver avuto.
Il motore gira interamente on-premise — nessun callback verso il cloud, nessuna API LLM esterna, il tuo parco di source control non lascia mai la tua rete. Per lo stesso motivo per cui un server di source control è la radice di fiducia della tua supply chain, la cosa che lo valida non dovrebbe spingere la tua topologia nel cloud di qualcun altro. Guarda come funziona il modello di validazione continua, o leggi il caso gemello dal lato CI della pipeline nei nostri approfondimenti su TeamCity CVE-2026-63077 e Gitea CVE-2026-20896.
Patcha oggi alla 19.2.4, 19.1.6, 19.0.8 o 18.11.11. Poi scopri — dall'evidenza, non da una stima — se qualcuno è arrivato prima.