Tornar al Blog

El procediment oficial per recuperar un GitLab comença amb un DELETE

Unitat de cinta LTO-6 i ranures d'una biblioteca IBM TS3500
Una còpia desada i una còpia que es pot llegir no es comproven igual. Foto: LTO-6 tape drive & IBM TS3500 slots, de vaxomatic, via Wikimedia Commons, CC BY 2.0. Retallada, enfosquida i amb rètols superposats.

El 12 d'octubre GitLab va publicar tres versions alhora —19.4.2, 19.3.5 i 19.2.8— per CVE-2026-97229, un desbordament d'enter al compilador d'expressions regulars de CI/CD puntuat amb un CVSS 10.0. La nota de la publicació el descriu com un error que «could have allowed an unauthenticated user to execute arbitrary code…». GitLab.com ja executava la versió pedaçada i els clients de GitLab Dedicated no han de fer res; el servidor que tens a la planta de sota, sí.

A la mateixa pàgina, sota «Important notes on upgrading», hi ha aquesta línia: «This patch will cause downtime during the upgrade as migrations must complete before GitLab can start». L'epígraf que l'encapçala és «Single-node instances», que és com està muntat gairebé tot el GitLab autogestionat que ens trobem en empreses petites i mitjanes. Aplicar el pedaç crític vol dir, allà, aturar el servei fins que acabin les migracions de base de dades. La 19.3.5 afegeix, a més, migracions que s'executen després del desplegament.

La pregunta que arriba després del reinici

Si la teva instància estava en una versió afectada i permetia que hi entrés gent de fora, pedaçar no tanca l'assumpte: algú ha de decidir si es dóna per compromesa. I si es dóna, la feina deixa de ser una actualització i passa a ser una reconstrucció amb rotació de credencials.

A l'agost ja vam explicar què s'emporta de debò una còpia de GitLab i per què el fitxer de secrets es queda fora —clonar el repositori no és tenir còpia de GitLab—. El resum: gitlab-backup create no desa /etc/gitlab, i la raó que dóna la documentació és bona, «Storing encrypted information in the same location as its key defeats the purpose of using encryption in the first place».

El que no vam explicar llavors és què passa el dia que aixeques aquella còpia en una altra màquina i el fitxer no hi és, o hi és però és d'una altra instal·lació. Hi ha procediment documentat per a això. Comença esborrant.

L'advertiment que encapçala el procediment

La guia de resolució de problemes de GitLab reparteix tres avisos en dos blocs abans de qualsevol ordre: «The steps in this section can potentially lead to data loss on the previously listed items», «Consider opening a Support Request if you're a Premium or Ultimate customer» i, sota un encapçalament propi, «Be sure to create a full database backup before attempting any changes». Cal repetir-los, perquè el que ve després s'executa contra la base de dades a mà i no té desfer.

Per a les variables de CI/CD, el procediment és exactament això:

DELETE FROM ci_group_variables;
DELETE FROM ci_variables;

I per als tokens dels runners, cinc sentències sobre quatre taules, amb els comentaris tal com vénen a la documentació:

-- Clear project tokens
UPDATE projects SET runners_token = null, runners_token_encrypted = null;
-- Clear group tokens
UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
-- Clear instance tokens
UPDATE application_settings SET runners_registration_token_encrypted = null;
-- Clear key used for JWT authentication
-- This may break the $CI_JWT_TOKEN job variable:
-- https://gitlab.com/gitlab-org/gitlab/-/issues/325965
UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
-- Clear runner tokens
UPDATE ci_runners SET token_encrypted = null;

L'avís que acompanya aquest bloc és el que convé llegir dues vegades: «The final UPDATE operation stops the runners from being able to pick up new jobs. You must register new runners».

Falta la part d'integracions i webhooks, que es resol amb un TRUNCATE sobre vuit taules en cascada, i la del segon factor, que la documentació despatxa desactivant-lo per a tots els usuaris perquè cadascú el torni a donar d'alta. Dir-ne restaurar seria generós: el que es fa és buidar el que ja ningú no pot llegir perquè el servei arrenqui, que és l'única cosa que es pot fer amb un valor xifrat la clau del qual no existeix.

Nou coses inaccessibles, i cap és el codi

La mateixa guia enumera què queda inaccessible quan la clau es perd. Són nou: variables de CI/CD, integració amb Kubernetes i GCP, dominis personalitzats de Pages, seguiment d'errors de projecte, autenticació dels runners, rèplica de projectes, integracions, webhooks i tokens de desplegament.

La rèplica de projectes és la que es trenca sense soroll: el mirall deixa de replicar i, si la teva còpia secundària de codi en depenia, es queda congelada a la data de l'incident sense que salti cap alarma.

A la llista no hi surt el codi. Els repositoris són a la còpia i tornen sencers, i per això aquest forat aguanta anys sense que ningú el vegi: la prova de restauració s'acaba quan apareix el git log de sempre i tothom respira. La maquinària que empeny aquest codi fins a producció no entra en aquesta prova.

El que costa tornar a escriure el que s'ha esborrat

El DELETE triga un segon. La factura arriba després, quan cal tornar a posar cada variable al seu lloc, i per a això cal saber quin valor tenia. Si la contrasenya del registre de contenidors, la clau del proveïdor de núvol o el token del sistema de tiquets vivien únicament en aquell camp xifrat, l'única còpia d'aquella credencial era dins de l'aplicació que acabes de buidar.

Segons la nostra experiència, aquí hi ha la conversa que costa: el gestor de contrasenyes de l'empresa i el panell de variables del CI fa anys que divergeixen sense que ningú els compari.

La lletra petita de la precondició

La nota de GitLab parla d'un usuari no autenticat; l'anàlisi de Rapid7, recollida per Help Net Security, hi afegeix la condició completa: l'atacant ha de poder pujar a una branca d'un projecte públic «a malicious CI/CD configuration file .gitlab-ci.yml, and a repository path containing UTF-8 characters». Els investigadors van reproduir l'execució de codi sobre la imatge oficial de GitLab CE 19.4.1 i la mateixa entrada no va funcionar contra la 19.4.2.

La diferència no canvia si cal pedaçar —cal pedaçar, i Rapid7 recomana fer-ho amb urgència, fora dels cicles de pedaços habituals—, però sí que canvia quantes hores tens i què cal mirar primer. Si a la teva instància un usuari qualsevol pot crear un projecte públic i empènyer una branca, la precondició es compleix omplint un formulari d'alta. Si és darrere la VPN i només hi entra gent amb nòmina, tens més marge, cosa diferent d'estar fora de perill. En el moment de l'anàlisi de Rapid7 no hi havia explotació confirmada a la vida real.

La comprovació que no és ràpida

Hi ha una tasca que respon, sobre la instància viva, si tot el que està xifrat encara es pot llegir:

sudo gitlab-rake gitlab:doctor:secrets VERBOSE=1

Recorre tots els valors xifrats de la base de dades i comprova que es desxifren amb el fitxer de secrets actual. Resumeix amb una línia del tipus Total: 1 row(s) affected, i amb VERBOSE=1 diu a més quines files i columnes fallen, amb noms com Group[10].runners_token. La mateixa documentació avisa que «This can take a very long time, depending on the size of your database, as it checks all rows in all tables», o sigui que no és cosa de llançar-la a les onze del matí d'un dimarts sense mirar la càrrega.

Si aquest número no és zero, ja hi ha valors que ningú no pot llegir, avui, amb la instància funcionant i el panell en verd.

El que dónes per perdut, decidit abans

La part que gairebé mai no està escrita és la decisió prèvia: què penses recuperar, què penses refer i, sobretot, on viu la còpia mestra de cada cosa. Es pren a plena llum i sense pressa, i ocupa cinc línies en mitja pàgina:

  • Variables de CI/CD. La còpia mestra és al gestor de contrasenyes o només a GitLab? Si la resposta honesta és «hauríem d'anar preguntant», el que falta és un inventari de credencials.
  • Runners. Tornar-los a registrar surt barat sempre que algú sàpiga quants n'hi ha i en quines màquines. Aquesta llista, existeix fora de la mateixa instància que acabes de perdre?
  • Tokens de desplegament. Qui els consumeix a l'altre costat: un servidor, un clúster, el proveïdor de núvol. Anul·lar-los sense aquesta llista deixa serveis aturats sense que ningú sàpiga per què.
  • Segon factor. Desactivar-lo per a tothom és una línia a la documentació i un matí de feina d'una persona avisant i verificant identitats.
  • Rèplica, integracions i webhooks. Apunta avui quins n'hi ha, perquè són l'últim que algú troba a faltar i el primer que trenca un flux de treball en silenci.

Restaurar i respondre demanen coses diferents

Si la conclusió de l'anàlisi és que el servidor va estar compromès, tot el que aquell servidor podia desxifrar s'ha de donar per cremat: variables, tokens, claus de desplegament. Per al que serveix llavors el fitxer de secrets és per llegir què hi havia i poder-ho rotar allà on es consumeix, que és una feina diferent i força més llarga.

Les dues tasques tiren en direccions contràries: restaurar vol la clau viva i la resposta a l'incident la vol morta. Per això l'ordre es decideix abans, en fred, igual que quan no hi ha pedaç disponible i toca governar el risc amb el que hi ha —la teva política de pedaços no contempla que no hi hagi pedaç—. Aquí pedaç n'hi ha, i tot i així la meitat de la feina es queda fora del que el pedaç resol.

El que queda apuntat

El pedaç d'aquest dilluns és urgent i s'aplica amb una aturada curta. El que no cap en aquesta finestra és esbrinar si, el dia que calgui aixecar la còpia en una altra màquina, el que torna és un GitLab funcionant o un GitLab amb l'historial intacte i les credencials buides. La tasca de comprovació triga el que trigui, però això ho respon avui.

Fonts (consultades el 14-10-2026): les versions, la data, el CVSS 10.0, la descripció de CVE-2026-97229, l'avís d'aturada durant l'actualització i la situació de GitLab.com i Dedicated surten de la nota del pedaç crític 19.4.2, 19.3.5 i 19.2.8. La precondició completa, la reproducció sobre la imatge 19.4.1, l'absència d'explotació confirmada i la recomanació d'actualitzar fora de les finestres habituals són de l'anàlisi de Rapid7 recollida a Help Net Security. Els avisos previs, les sentències SQL i la llista de les nou coses inaccessibles, de la guia de resolució de problemes de còpies; el motiu pel qual la configuració no va dins de la còpia, de la documentació de còpies de seguretat; i la tasca gitlab:doctor:secrets, el seu mode VERBOSE i l'avís sobre la seva durada, de la pàgina de tasques de comprovació. No hem reproduït la vulnerabilitat: aquí no hi ha anàlisi pròpia de l'error, només lectura de fonts públiques i la part operativa. Són nostres la lectura que el que no torna és la maquinària i no el codi, l'ordre de la decisió prèvia, el guió de cinc línies i l'observació sobre com està muntat el GitLab autogestionat que ens trobem.

Aixecar la còpia en una altra màquina, abans de necessitar-ho

A everyWAN muntem i assagem plans de recuperació davant de desastres en què el que es mesura és el servei aixecat i en funcionament; revisem què queda exposat i què cal rotar des de ciberseguretat; i mantenim al dia el stack de dades i aplicacions sobre el qual treballa un equip de desenvolupament.

Parlar amb everyWAN

Etiquetes:

Compartir:

Subscriu-te al nostre butlletí

Per rebre històries del món IT, novetats d'everyWAN i ofertes exclusives per a subscriptors, dona't d'alta a la nostra llista de correu

everyWAN
everyWAN