Node.js saugumo atnaujinimas: ar Jūsų versija dar gauna pataisas?
Spalio 21 dieną Node.js išleido saugumo pataisas 22, 24 ir 26 release line. Kurios versijos yra saugios, kodėl Node.js 18 ir 20 pataisų negaus ir kaip patikrinti, kurią versiją naudoja Jūsų programa.
Spalio 21 dieną Node.js išleido saugumo pataisas 22, 24 ir 26 release line. Kurios versijos yra saugios, kodėl Node.js 18 ir 20 pataisų negaus ir kaip patikrinti, kurią versiją naudoja Jūsų programa.
Saugumo pataisas gavo tik tos release line, kurios dar palaikomos, ir saugios yra versijos 22.23.4, 24.22.1 ir 26.12.1 arba naujesnės toje pačioje. Node.js 18 ir 20 palaikymą jau prarado (end of life), todėl šiame Node.js saugumo atnaujinime saugumo pataisos joms nėra ir nebus: jei Jūsų programa veikia su kuria nors iš jų, atnaujinimas reiškia perėjimą į kitą release line.
Trečiadienį, spalio 21 dieną, Node.js projektas išleido saugumo leidimus visoms trims palaikomoms release line, ir tą pačią dieną PHP išleido neeilines pataisas pažeidžiamumams, kurie gavo pavadinimą PHP2Shell, tačiau tai du atskiri įvykiai su skirtingu pavojingumu. Node.js leidimas buvo paskelbtas iš anksto, rimčiausius jo pažeidžiamumus projektas įvertino kaip aukštus, o ne kritinius, ir pranešime neminima nei laikinų sprendimų, nei atakų realioje aplinkoje. Tai neleidžia atnaujinimo atidėti, bet perkelia dėmesį: šį kartą didžiausia rizika yra ne pačiame leidime, o versijose, kurios jo negavo.
Kas buvo pataisyta spalio Node.js saugumo atnaujinime
Node.js pranešime išvardyta dešimt pažeidžiamumų: keturis projektas įvertino kaip aukštus, tris kaip vidutinius ir tris kaip žemus, bet CVSS įvertinimų projektas šį kartą nepaskelbė, todėl šiame straipsnyje naudojamas tas pats vertinimas.
Rimčiausias iš jų yra CVE-2026-111497. Projektas jį vadina Brotli dekoderio out-of-bounds write, kuris leidžia nuotolinį kodo vykdymą (RCE), ir vertina kaip aukštą. Brotli yra glaudinimo formatas, kurio dekoderis įtaisytas į Node.js, o leidimo pastabose pataisa aprašyta kaip pakeitimas šioje įtaisytoje bibliotekoje. Kokiu keliu pažeidžiamumas pasiekiamas, pranešime nepasakyta, ir Brotli kūrėjų pataisos aprašymas kalba tik apie tai, kad netinkamas duomenų srautas dabar atpažįstamas anksčiau. Todėl čia neminimos konkrečios funkcijos: saugiai galima pasakyti tik tiek, kad dekoderio klaida labiausiai liečia programas, kurios išskleidžia Brotli duomenis iš šaltinio, kuriuo jos negali pasitikėti.
Trys kiti pažeidžiamumai liečia TLS sertifikatų tikrinimą, ir tai nėra vienas ir tas pats atvejis. Pirmasis, su aukštu įvertinimu, liečia tik 26 ir 24 release line: hostname verification galima apeiti, jei IP adresas užrašytas pilno pločio skaitmenimis, pavyzdžiui, 127.0.0.1. Antrasis, taip pat aukštas, liečia visas tris release line: tikrinimą galima apeiti, jei hostname galima negriežtai perskaityti kaip IP adresą. Trečiasis yra vidutinis ir taip pat liečia visas tris release line: nestandartinis IPv4 užrašas leidžia sertifikate nurodytam DNS vardui paliudyti IP adresą. Leidimo pastabose pataisos suformuluotos trumpai: netipiškai užrašyti IP adresai dabar atmetami, ir atskirai ištaisyta IP adresų normalizavimo regresija. Visais trimis atvejais kalbama apie akimirką, kai Node.js veikia kaip klientas, tai yra kai pats kuria šifruotą jungtį su kitu serveriu, o ne apie akimirką, kai jis aptarnauja savo lankytojus.
Ketvirtasis aukšto įvertinimo pažeidžiamumas yra dns.resolve funkcijoje, kuri nukirsdavo vardus, kuriuose yra nulinis simbolis. Tarp vidutinių yra HTTP jungčių pakartotinio naudojimo klaida, kurioje atsakymas, įrašytas į jungtį prieš išsiunčiant užklausą, galėjo būti apdorotas kaip atsakymas į šią užklausą, ir klaida, dėl kurios crypto.randomUUID() ir randomInt() atsitiktinumo talpykla buvo išsaugota startup snapshot ir viename vykdomajame faile, todėl kiekvienas procesas kartodavo tas pačias reikšmes. Trys žemo įvertinimo pažeidžiamumai liečia ZIP failų apdorojimą ir Node.js prieigos teisių modelį.
Atsitiktinumo talpyklos klaidą verta suprasti tiksliau, nes įprastu atveju ji nieko nepaveikia. Ji liečia tik projektus, kurie paleidžiami iš pačių sukurto startup snapshot arba platinami kaip vienas vykdomasis failas (single executable application, SEA), ir ten ji reiškia, kad kiekvienas procesas, paleistas iš to paties failo, gavo tas pačias „atsitiktines“ reikšmes. Jei tokiame projekte su crypto.randomUUID() arba randomInt() buvo kuriami identifikatoriai ar laikini kodai, jie galėjo kartotis tarp procesų, todėl po pataisos verta patikrinti, ar kuri nors iš šių reikšmių nėra naudojama ten, kur ji turi būti neatspėjama.
Leidimas atnaujina ir kelias įtaisytąsias priklausomybes, priklausomai nuo release line: c-ares, OpenSSL, SQLite ir Undici, kuria remiasi įtaisytoji fetch funkcija. Taip pat atnaujintas CA store dėl sukompromituoto eMudhra tarpinio sertifikato, ir TLS jungtys dabar atmeta grandines, kuriose yra užblokuoti viešieji raktai.
Kurios versijos yra saugios
Pataisytos versijos yra trys, po vieną kiekvienai palaikomai release line: 22.23.4, 24.22.1 ir 26.12.1. Viskas, kas savo release line yra seniau, yra paveikta. Ne visi dešimt pažeidžiamumų liečia visas release line: 26 release line turi visus dešimt, 24 release line — aštuonis, o 22 release line — septynis, nes dvi žemo įvertinimo klaidos yra tik naujausioje ir viena TLS klaida neliečia 22 release line.
Atnaujinimas tos pačios release line ribose yra mažiausias įmanomas žingsnis, ir paprastai tai saugiausias pakeitimas, kurį galima padaryti gamybinėje aplinkoje. Vis dėlto ir jis gali pakeisti elgesį, ir šį kartą yra konkretus pavyzdys: TLS tikrinimo pataisa dabar atmeta netipiškai užrašytus IP adresus. Jei kuri nors programa jungtyse su kitu serveriu anksčiau naudojo tokį užrašą, po atnaujinimo jungtis gali nepavykti. Tai pataisyta saugumo spraga, o ne nauja klaida, tačiau tą verta žinoti prieš atnaujinant, o ne po to.
Release line yra svarbesnė už versijos numerį
Iki Node.js 26 kiekviena pagrindinė versija eina per vieną ciklą: pirmiausia ji yra dabartinė versija (Current), tada lyginio numerio versijos gauna aktyvų ilgalaikį palaikymą (Active LTS), paskui pereina į Maintenance LTS, kuriame gauna tik kritines klaidų pataisas ir saugumo pataisas, ir galiausiai palaikymas baigiasi visai (end of life), o nelyginio numerio versijos iki 25 release line ilgalaikio palaikymo negavo. Nuo Node.js 27 ciklas keičiasi: pagal leidimų grafiką ilgalaikį palaikymą gaus kiekviena release line, ir visus 30 palaikymo mėnesių ji liks Active LTS fazėje, be Maintenance LTS. Projektas pats rašo, kad gamybinėms programoms reikia naudoti tik Active LTS arba Maintenance LTS versijas.
Dabartinėms release line artimiausi fazės pokyčiai įvyksta dviem datomis: pagal Node.js leidimo grafiką 24 release line į Maintenance LTS perėjo spalio 20 dieną, dieną prieš saugumo leidimą, o 26 release line ilgalaikį palaikymą gaus spalio 28 dieną. 22 release line yra Maintenance LTS fazėje nuo 2025 metų spalio 21 dienos ir palaikymą praras 2027 metų balandžio 30 dieną, o 24 release line jį praras 2028 metų balandžio 30 dieną.
Praktinė prasmė paprasta: klausimas „ar turime naujausią versiją“ pats savaime nedaug pasako, o naudingas yra klausimas „kurioje release line esame ir iki kurios datos ji gaus pataisas“. Pirmasis klausimas atsakymą keičia kas mėnesį, antrasis — kartą per porą metų, ir būtent todėl antrąjį lengva pamiršti.
Node.js 18 ir 20: saugumo pataisos nebus
Node.js pranešime yra sakinys, kuris šį kartą svarbesnis už visus dešimt pažeidžiamumų: versijos, kurių palaikymas pasibaigęs (end of life), saugumo leidime visada yra paveiktos, ir pataisos joms neišleidžiamos nei dabar, nei vėliau, nes release line, kuriai palaikymas pasibaigęs, nebegauna nė vieno leidimo.
Pagal leidimo grafiką 16 release line palaikymą prarado 2023 metų rugsėjo 11 dieną, 19 release line — 2023 metų birželio 1 dieną, 18 release line — 2025 metų balandžio 30 dieną, o 20 release line — 2026 metų balandžio 30 dieną. Paskutinė data svarbiausia: 20 release line palaikymą prarado prieš nepilnus šešis mėnesius, ir projektas, kuris buvo pradėtas su ja, vis dar gali veikti be jokių matomų problemų. Būtent tai padaro padėtį klastingą, nes niekas jos veikime nerodo, kad saugumo pataisos jai nebepriklauso.
Įmonėms, kurios negali greitai pereiti į palaikomą release line, Node.js pranešimas mini vieną galimybę: komercinį palaikymą versijoms po Maintenance LTS siūlo OpenJS Ecosystem Sustainability Program partneriai — tai mokama paslauga ir laikinas sprendimas, o ne pakaitalas perėjimui.
Kaip patikrinti, kurią Node.js versiją naudoja Jūsų programa
Patikra užima minutes, bet yra viena vieta, kur ją lengva padaryti neteisingai: Node.js versija, kurią rodo terminalas, ne visada yra ta pati, su kuria veikia programa.
Hostingas su cPanel — naudojamą versiją rodo skyrius Software → Setup Node.js App, kur kiekviena programa turi savo eilutę ir versija pasirenkama iš sąrašo, ir jame yra tik tos versijos, kurias serveryje įdiegė hostingo teikėjas. Komanda node -v tokiame hostinge gali parodyti kitą versiją nei šis nustatymas, todėl žiūrėkite būtent į atitinkamą eilutę.
Nuosavas serveris — komanda node -v rodo tą versiją, kuri sistemos kelyje (PATH) stovi pirma, bet procesų tvarkyklė, pavyzdžiui, PM2 arba systemd servisas, gali paleisti programą su visai kitu vykdomuoju failu. Patikimiausias atsakymas yra tas, kurį procesas pats praneša apie save: process.version reikšmė, pavyzdžiui, įrašyta į žurnalą paleidimo metu.
Konteineriai — Docker aplinkoje versiją lemia container image (base image), o ne pagrindinis kompiuteris (host). Container image, surinktas iki spalio 21 dienos, pataisos neturi, kad ir kiek kartų konteineris būtų paleistas iš naujo, todėl container image reikia surinkti iš naujo su atnaujintu base image.
Jei prieigos nėra — tada klausimas skirtas hostingo teikėjui arba kūrėjui, kuris ją prižiūri: formuluotė, kuri taupo susirašinėjimą: „Kurią Node.js versiją naudoja mūsų programa? Ar savo release line ji yra bent 22.23.4, 24.22.1 arba 26.12.1? Jei ji yra release line be palaikymo, pavyzdžiui, 18 arba 20, kada planuojamas perėjimas?“
Ką daryti šiandien
Šiandienos tvarka tokia: pirmiausia atnaujinti Node.js iki pataisytos versijos savo release line ir paleisti iš naujo kiekvieną procesą, kuris ją naudoja, tada iš naujo surinkti viską, kur runtime yra įtaisytas, ir tik po to planuoti perėjimą tiems projektams, kurie veikia release line be palaikymo.
Pirmiausia atnaujinkite tos pačios release line ribose — iki 22.23.4, 24.22.1 arba 26.12.1, pagal tai, kurioje release line esate. Hostingo atveju tai padaro teikėjas, o Jūsų darbas yra įsitikinti, kad programa naudoja atnaujintą versiją.
Antra, paleiskite procesus iš naujo — procesas, kuris jau veikia, toliau naudoja tą Node.js, su kuriuo buvo paleistas, ir failo pakeitimas diske jo nepaveikia. Tas pats galiojo ir PHP2Shell atveju: paketas pakeistas, bet senas procesas toliau veikia su senu kodu.
Trečia, iš naujo surinkite tai, kur runtime yra įtaisytas — Docker container image reikia surinkti iš naujo su atnaujintu base image. Jei programą platinate kaip vieną vykdomąjį failą (SEA), jame įtaisytas pats Node.js, todėl sistemoje įdiegtos versijos atnaujinimas jo nepaveikia, ir failą reikia surinkti iš naujo su pataisyta versija; tas pats liečia startup snapshot, kuriuos paveikia atsitiktinumo talpyklos klaida.
Ketvirta, jei esate 18 arba 20 release line, suplanuokite perėjimą — tai didesnis darbas nei atnaujinimas tos pačios release line ribose, todėl jį verta pradėti dabar, o tvarka aprašyta kitame skyriuje.
Kaip pereiti nuo Node.js 18 arba 20
Perėjimas tarp pagrindinių versijų nėra vienos komandos darbas, ir jį verta daryti iš eilės. Pirmiausia reikia pasirinkti tikslą: daugeliu atvejų tai 24 release line, kuri pataisas gaus iki 2028 metų balandžio 30 dienos; 22 release line yra protingas pasirinkimas tik tada, jei kuri nors svarbi priklausomybė dar nepalaiko 24 release line, nes jos palaikymas baigsis metais anksčiau.
Tada reikia rasti visas vietas, kur projektas nurodo savo Node.js versiją, nes jų beveik visada yra kelios: package.json laukas engines, failai .nvmrc arba .node-version, Dockerfile base image, continuous integration (CI) aplinkos konfigūracija ir hostingo skydelio nustatymas. Jei pakeičiama tik dalis jų, skirtingose aplinkose veikia skirtingos versijos, ir klaidos pasirodo ten, kur jas sunkiausia rasti.
Po to projektą testinėje aplinkoje reikia įdiegti iš naujo su nauja versija ir paleisti testus. Ypatingas dėmesys priklauso paketams, kuriuose yra kompiliuotas kodas: jie surenkami konkrečiai Node.js versijai, todėl po perėjimo juos gali tekti surinkti iš naujo arba atnaujinti. Node.js kiekvienai pagrindinei versijai skelbia pakeitimų sąrašą, kuriame atskirai pažymėti pakeitimai, galintys sulaužyti esamą kodą, ir jį verta perskaityti prieš perėjimą, o ne po jo.
Tik tada eina gamybinė aplinka: versijos keitimas, procesų paleidimas iš naujo ir patikra, kad process.version rodo naują versiją. Sena versija kelias dienas gali likti pasiekiama tam atvejui, jei tektų grįžti, bet ne ilgiau, nes būtent ji yra versija, kuriai pataisos daugiau nebebus.
Kas neatnaujinama kartu su Node.js
Node.js atnaujinimas pataiso patį runtime ir bibliotekas, kurios jame įtaisytos, bet ne viską, ką programa naudoja, ir būtent čia dažniausiai lieka skylės, kurių niekas nemato.
Atskiri įdiegti paketai — jei projektas savo priklausomybėse naudoja undici paketą iš npm, o ne įtaisytąją fetch, šis paketas yra projekto node_modules aplanke, ir Node.js leidimas jo nepaliečia. Tas pats liečia visas kitas priklausomybes: jas atnaujina paketų tvarkyklė, ir tik tada, kai kas nors ją paleidžia.
CA store — pagal numatytuosius nustatymus Node.js naudoja ne operacinės sistemos sertifikavimo įstaigų sąrašą, o savo įtaisytąjį, ir dokumentacijoje pasakyta, kad tai Mozilla sąrašo fiksuota kopija, kuri užfiksuojama leidimo metu. Vadinasi, tokius pakeitimus, kaip šio leidimo reakciją į sukompromituotą eMudhra tarpinį sertifikatą, programa gauna tik kartu su runtime atnaujinimu, o ne kartu su operacinės sistemos atnaujinimais, nebent ji specialiai sukonfigūruota naudoti sistemos sąrašą.
Kaip nepraleisti kito leidimo
Node.js saugumo leidimus paskelbia iš anksto savo saugumo puslapyje, nurodydamas planuojamą leidimo dieną, ir šį kartą būtent taip ir įvyko. Vadinasi, šis trečiadienis nebuvo staigmena tiems, kas šį puslapį stebi: atnaujinimą buvo galima suplanuoti iš anksto, o ne ieškoti jam laiko tą pačią dieną.
Praktiškai tai reiškia, kad kas nors turi būti atsakingas už šią stebėseną. Profesionalaus hostingo atveju tai daro teikėjas, o nuosavame serveryje arba projekte, kurį prižiūri pati komanda, verta žinoti, kas būtent seka projekto pranešimus, kas nusprendžia dėl atnaujinimo ir kas patikrina, kad po jo viskas veikia. Jei į šiuos klausimus atsakymas yra „niekas konkrečiai“, būtent ten ir yra didžiausia rizika, o ne kuriame nors iš dešimties pažeidžiamumų.
Jei Node.js Jums tėra build tool
Daugelyje Laravel ir WordPress interneto svetainių Node.js serveryje iš viso neveikia: jis paleidžia Vite ar panašų build tool, kuris iš pirminio kodo paruošia CSS ir JavaScript failus, ir paskui sustoja. Tokiu atveju padėtis skiriasi nuo programos, kuri pati aptarnauja užklausas, nes build procesas neatsako į užklausas iš interneto ir neišskleidžia duomenų, kuriuos jam atsiunčia nežinomi lankytojai.
Tai, kad skiriasi, nereiškia, kad tai nesvarbu — build tool veikia kūrėjų kompiuteriuose ir CI aplinkoje, atsisiunčia paketus ir kuria jungtis su kitais serveriais, o pažeidžiamumų aprašymai yra per trumpi, kad būtų galima saugiai pasakyti, kurie iš šių kelių paveikti. Atnaujinti Node.js verta ir ten, tik teisinga tvarka: pirmiausia serveriai, kur Node.js veikia gyvai, paskui kūrėjų kompiuteriai ir CI aplinka.
Yra ir antra priežastis, nesusijusi su šia savaite: build aplinka dažnai lieka su ta Node.js versija, su kuria projektas kadaise buvo pradėtas, ir tada vieną dieną nauja įrankio versija paprasčiausiai atsisako su ja veikti. Perėjimas į palaikomą release line tada vyksta skubant ir netinkamu metu, todėl jį lengviau padaryti dabar, kol tai yra suplanuotas darbas.
Ką tai reiškė mūsų hostinge
Mūsų profesionalus hostingas yra vieta mūsų pačių serveryje, ir kiekvienas klientas jame renkasi versiją per hostingo skydelį. Mūsų serveryje Node.js 22 ir 24 release line jau veikia su pataisytomis versijomis 22.23.4 ir 24.22.1. Klientams, kurių projektai jas naudoja, nieko daryti nereikia, išskyrus įsitikinti, kad procesas po atnaujinimo paleistas iš naujo.
Sąžiningai reikia pasakyti ir kitą pusę: serveryje pasirinkimui vis dar prieinamos ir release line, kurioms palaikymas pasibaigęs, ir joms pataisos nėra — nei mūsų, nei kurio nors kito serveryje, nes Node.js tokios pataisos neišleidžia. Jei Jūsų projektui pasirinkta kuri nors iš jų, atnaujinimas reiškia perėjimą į 22 arba 24 release line, ir tai geriausia daryti kartu su patikra, kad po perėjimo viskas veikia taip pat kaip anksčiau.
Mūsų profesionalus hostingas prasideda nuo 45 € per mėnesį, ir prižiūrimi runtime yra dalis to, už ką šioje sumoje mokama. Jei Jūsų programa dar veikia su Node.js 18 arba 20, aptarsime perėjimą, dar prieš tai, kai jį padaryti privers kito saugumo leidimo diena.
Dažniausiai užduodami klausimai.
Kuri Node.js versija yra saugi?
Saugios yra 22.23.4, 24.22.1 ir 26.12.1 arba naujesnės versijos toje pačioje release line. Viskas, kas savo release line yra seniau, yra paveikta. Versijoms, kurių release line jau pasiekė end of life, pavyzdžiui, Node.js 18 ir 20, saugios versijos nėra iš viso, nes joms pataisos neišleidžiamos.
Turiu Node.js 18 arba 20. Ką daryti?
Abiem release line palaikymas pasibaigęs: 18 release line — 2025 metų balandžio 30 dieną, 20 release line — 2026 metų balandžio 30 dieną. Pataisos joms nėra ir nebus, todėl vienintelis sprendimas yra perėjimas į palaikomą release line. 24 release line pataisas gaus iki 2028 metų balandžio 30 dienos, 22 release line — iki 2027 metų balandžio 30 dienos. Perėjimą verta pirmiausia išbandyti testinėje aplinkoje.
Ar šis Node.js saugumo atnaujinimas yra tas pats, kas PHP2Shell?
Ne. Abu įvykiai buvo spalio 21 dieną, tačiau jie yra atskiri. PHP2Shell buvo du kritiniai pažeidžiamumai pačiame PHP. Node.js saugumo leidimas buvo paskelbtas iš anksto, rimčiausi jo pažeidžiamumai įvertinti kaip aukšti, ir pranešime neminimos atakos realioje aplinkoje.
Ar pakanka atnaujinti Node.js, jei programa jau veikia?
Ne, procesą reikia paleisti iš naujo. Procesas, kuris jau veikia, toliau naudoja tą Node.js, su kuriuo buvo paleistas. Jei programa yra Docker container image arba platinama kaip vienas vykdomasis failas (SEA), jame įtaisytas pats Node.js, ir jį reikia surinkti iš naujo su pataisyta versija.
Mūsų Laravel ar WordPress svetainėje Node.js naudojamas tik Vite surinkimui. Ar tai mus liečia?
Mažiau nei programą, kuri pati aptarnauja užklausas, nes build procesas neatsako į užklausas iš interneto. Vis dėlto build tool atsisiunčia paketus ir kuria jungtis su kitais serveriais, todėl Node.js verta atnaujinti ir kūrėjų kompiuteriuose bei integracijos aplinkoje, tik po serverių.
Ar yra laikinų sprendimų, jei atnaujinti iš karto negalite?
Node.js pranešime laikini sprendimai neminimi. Vienintelė rekomendacija yra naudoti palaikomą versiją pagal leidimo grafiką. Versijoms, kurioms atėjo end of life, Node.js mini komercinį palaikymą, kurį siūlo OpenJS Ecosystem Sustainability Program partneriai.
Kaip sužinoti, kurią Node.js versiją programa naudoja cPanel hostinge?
Skyriuje Software → Setup Node.js App, kur kiekviena programa turi savo eilutę su pasirinkta versija. Komanda node -v terminale gali parodyti kitą versiją nei programos nustatymas, todėl žiūrėkite būtent į programos eilutę.
Serveriai, talpinimas ir priežiūra ES — Frankfurte, Helsinkyje ar Rygoje, su stebėsena 24/7. Pilnas administravimas: atnaujinimai, saugumas ir našumas, automatinės atsarginės kopijos ir patikrintas jų atkūrimas, SSL sertifikatai, CDN ir apsauga nuo DDoS. Perkeliame iš dabartinio talpinimo paslaugų teikėjo be prastovų ir keičiame mastelį pagal apkrovą.