Ga beskjed til 70 utviklere etter Shai Hulud 2.0: «Stopp alt»

– Hvis det er én ting denne hendelsen gjorde tydelig, er det hvor viktig det er at organisasjoner har moden kompetanse i Node-økosystemet, skriver Åsmund Røst Wien.

Åsmund Røst Wien, teamleder og lead konsulent hos Twoday, forteller hvordan de taklet Shai Hulud-ormen.
Publisert

✍ leserinnlegg

Dette er et leserinnlegg fra en ekstern skribent, som betyr at innholdet ikke nødvendigvis speiler kode24s meninger. Vil du også bidra? Send oss en epost på [email protected], eller les mer her!

Hva skjer når, helt uten forvarsel, popkulturens mest kjente sandorm formerer seg i et supply-chain-angrep midt i verdens største utvikler-økosystem? 

Man kan elske eller hate JavaScript, men når Node faller, da faller mye.

Vi skal innom en rekke tekniske og organisatoriske tiltak som fungerte for oss, og hvordan andre organisasjoner kan ruste seg for fremtidens Shai Hulud 3.0.

Hva skjedde?

Shai Hulud-ormen spredte seg raskt mellom hele verdens biblioteksforfattere, gjennom en kjede av pakkemanipulasjoner, kompromitterte utgivelser og gjennomtenkte preinstall-scripts. 

Du ble kompromitert før du i det hele tatt hadde begynt å jobbe. Angrepet var såpass “left shift” at det er svært få verktøy som enda har begynt å fungere. 

Selv med lockfiles og moderne CI, ble angrepet overraskende effektivt, fordi det utnyttet økosystemets svært komplekse dependency graph, som kanskje også er økosystemets største svakhet. 

Det er vanskelig å skrive “Hello React!” uten et fire-sifrert antall pakker.

Hvordan vi fikk kontroll

Da vi identifiserte den utløsende faktoren for angrepet, tok vi et felles valg: stopp alt. 

  • I et mijø med over 70 utviklere måtte vi spre ordet raskt og tydelig: «Ingen jobber mot Node før vi har oversikt!». 
  • Deretter stengte vi ned alle pipelines som installerte noe fra Node. Alt ble frosset. I full lockdown kunne ikke skaden bli verre. 
  • Deretter startet et omfattende arbeid i å se hva som var kjørt de siste par dagene, hvilke utviklere som hadde installert noe som helst i det aktuelle tidsrommet, og om skaden hadde skjedd, hadde vi sluppet unna?
  • Deretter var det på tide å innføre rutiner for hvordan å kunne plukke opp igjen utviklingsoppgaver uten å risikere å bli kompromittert; ormen var tross alt fortsatt svært aktiv der ute. 

Så hvilke tiltak kan man innføre for å være produktiv, selv mens et pågående supply-chain angrep i denne skalaen er i full aktivitet?

 

Deretter stengte vi ned alle pipelines som installerte noe fra Node. Alt ble frosset.

#1: Prioritere - jobbe “tynnere”

I et enterprise-miljø med svært mange Node-applikasjoner i ulike former og fasonger kan det være vanskelig å ha full oversikt over alt som rører seg. 

Først og fremst reduserte vi kognitiv og operasjonell risiko ved å minimere antall deler som var i bevegelse.

#2: Innføre en streng dependency graph

Når en kodebase hadde blitt prioritert innførte vi et regime som vi hadde blitt enige om på forhånd. 

Et av tiltakene våre var å låse dependency-grafen til et tidspunkt før angrepet startet. De fleste prosjektene våre benytter `pnpm` som pakkemanager, og der kan man enkelt tvinge at pakkene må ha nådd en viss alder før de er tillat å installere:

# pnpm-workspace.yaml 

minimumReleaseAge: 10080 # minutter (her: 7 døgn)

Med en karantenetid siden før angrepet startet var det mulig å garantere en at alle pakker som ble installert var trygge. Dette var en funksjon som kom med pnpm etter vi ble kjent med Shai Hulud for første gang i september.

#3: Frysing av dependency-resolution

For å hindre angrepet innførte vi to effektive grep i .npmrc-konfigurasjonen rundt om:

  1. Deaktivere alle install-scripts (ignore-scripts=true) Dette stoppet umiddelbart den aktive ormen, ved å hindre pre/postinstall-scripts.
  2. Fryse dependency-resolusjonen (frozen-lockfile=true) Dette sikrer at ingen pakker kan installeres med en annen versjon enn det som allerede står i lockfila. Med dette på plass i en dependency graph som er vrudert som trygg kan ingen utilsiktede oppgraderinger eller nye kompromitterte pakker snike seg inn. Dette er et midlertidig tiltak, men effektivt i en akuttfase.

Med disse tiltakene på plass begynner det å bli trygt å slippe alle utviklere løs, til og med om de ikke er kjempetrygge i Node.

#4: Pinnede versjoner

I våre prosjekter hadde vi allerede et strengt regime for å aktivt bruke lockfiles. 

Men stadig ser vi miljøer hvor lockfile ikke sjekkes inn og CI gladelig installerer alt det nyeste den kan, til enhver tid.

Hos oss var versjonsranges som ^ og ~ mye brukt, og det har vi nå valgt å legge bort. Ingen magi, kun eksplisitte versjoner.

#5: Caching av node_modules

Vi valgte også å standardisere package manager til pnpm. 

Dette er fordi pnpm håndterer avhengigheter på en mer forutsigbar og isolert måte enn npm og yarn. For oss betyr det færre overraskelser i installasjoner, og mer stabile bygg både lokalt og i CI. For ikke å nevne at standardiserte CI-løp er enklere å forvalte.

Vi valgte også å kun installere pakker fra vår private artifact feed i Azure DevOps. På denne måten kan vi, når faren inntreffer, bryte med NPM som upstream og hindre oss fra å installere nye, kompromiterte pakker. Dette er et sterkt verktøy i kombinasjon med å aldri installere pakker som er eldre enn f.eks. en uke.

Sammen spiller pnpm og en privat artifact feed godt sammen. Vi kan hindre upstream nedlastinger av de nyeste (kompromiterte) pakkene, og isolere oss fra omverdenen når alt brenner. Dessuten tilbyr pnpm lokal caching av pakker, så antall nedlastinger over internett reduseres både i det ene og det andre leddet. 

Vi kan også ha kontroll over hvilke pakker som tilgjengeliggjøres på feeden vår, fjerne gammelt skrot eller nytt ondsinnet rot, ved behov. 

Kompetanse i Node-økosystemet

Det er en kjent sak at mange elsker å hate JavaScript, og en kan kritisere Node så mye en vil. 

Det er liten tvil om at det er mange utfordringer med dette økosystemet, men det er også liten tvil om at teknologien har etablert seg som en bransjestandard.

Hvis det er én ting denne hendelsen gjorde tydelig, er det hvor viktig det er at organisasjoner har moden kompetanse i Node-økosystemet. Det handler ikke om å peke på hva noen ikke kan, men om å erkjenne at dependency-resolvere, registry-arkitektur og install-scripts er kritiske byggesteiner i moderne utvikling. Når det stormer, er det uvurderlig å ha folk som kjenner denne infrastrukturen godt nok til å manøvrere trygt.

Det er stor forskjell på utviklere som kjenner Node-økosystemet i dybden, og de som må slå opp grunnleggende konsepter som lockfiles i en krisesituasjon. Når ting brenner, hjelper det lite å være etterpåklok. 

Node er ikke «bare frontend». Det er en grunnmur i moderne utviklingsstakker, på tvers av disipliner. Vi kommer til å fortsette å prioritere moden Node-kompetanse – den er helt avgjørende når utviklingshverdagen plutselig står i brann.

Node er ikke «bare frontend». Det er en grunnmur i moderne utviklingsstakker, på tvers av disipliner.

The end?

I store enterprise-miljøer er det lett å tenke på Node som først og fremst et frontend-verktøy. 

Men erfaringene våre viser hvor mye av organisasjonens utviklingsflyt som faktisk hviler på dette økosystemet. 

Etter dette Shai Hulud-dramaet er det naturlig at mange stiller seg kritiske til NPM. Det er forståelig – men det er samtidig den plattformen vi alle står på. Vi skal nok snart se tilbake på Shai Hulud 2.0, men alle gode ting er tre. 

Det kommer flere angrep og dessverre kommer de aldri på et passende tidspunkt. 

Det er nok ikke siste gang vi møter på vår kjære sandorm.

Powered by Labrador CMS