Răspuns scurt
- Nu lăsăm node_modules și npm pe serverul de producție fiindcă fiecare pachet instalat acolo este cod străin executabil, iar npm CLI îi oferă atacatorului o unealtă de descărcare gata configurată.
- Construiește aplicația în CI, cu lockfile fixat, și copiază pe server doar artefactul rezultat.
- Dacă instalezi totuși dependențe pe server, folosește npm ci --omit=dev --ignore-scripts, niciodată npm install.
- Într-un container, etapa finală a unui build multi-stage conține doar runtime-ul Node și fișierele compilate, fără npm.
- Blochează scripturile de instalare printr-un .npmrc cu ignore-scripts=true și cere revizuirea lockfile-ului la fiecare pull request.
- Comanda acceptabilă pe producție
- npm ci --omit=dev --ignore-scripts
- Vectorul Shai-Hulud (2025)
- script preinstall, rulat la instalare
- Compromis chalk și debug (sept. 2025)
- 18 pachete, phishing 2FA pe un domeniu fals
- Ce rămâne în imaginea finală
- node, dist/ și dependencies; fără npm CLI
Ce găsește un atacator într-un node_modules de producție
Un node_modules complet conține de regulă de zece ori mai mult cod decât aplicația ta, inclusiv devDependencies: bundlere, compilatoare, unelte de test. Fiecare este o cale de execuție. npm CLI adaugă un client HTTP autentificat, cu token în ~/.npmrc și cache plin de tarball-uri. În 2025, pachete cu miliarde de descărcări săptămânale au fost compromise prin conturile de întreținător, iar payload-ul a rulat din preinstall, adică la instalare. Dacă instalarea se întâmplă pe server, serverul este locul în care rulează codul străin.
Build-ul în CI închide trei probleme deodată
Prima este suprafața de atac: pe server ajunge doar ce a produs build-ul, fără compilatoare și scripturi de pachet. A doua sunt secretele: cache-ul npm și tokenul rămân pe runner-ul de CI, nu pe o mașină expusă la internet. A treia este driftul: cu npm install pe server, versiunile pot diferi de cele testate, iar bug-ul apare doar în producție. Cu un artefact construit o singură dată și promovat între medii, ce a trecut testele este exact ce rulează la client.
Ce cer clienții din UE de la un furnizor din Moldova
Contractele cu clienți din Germania, Olanda sau România vin cu o anexă de securitate și, când procesezi date personale pentru ei, cu un contract de persoană împuternicită conform articolului 28 GDPR. Tot mai des apare cerința unui inventar de componente software și a unui proces documentat de gestionare a dependențelor. Un pipeline în care dependențele se instalează în CI, cu lockfile și fără scripturi, răspunde direct. Legea nr. 48/2023 privind securitatea cibernetică, în vigoare de la 1 ianuarie 2025, pune și ea accent pe riscurile din lanțul de aprovizionare.
Moduri de a pune dependențele pe producție, comparate| Metodă | Rulează scripturi de pachet | Reproductibil | Verdict |
|---|
| npm install pe server | da | nu | de evitat |
|---|
| npm ci --omit=dev --ignore-scripts | nu | da | acceptabil |
|---|
| Build în CI + artefact copiat | doar în CI | da | recomandat |
|---|
| Docker multi-stage fără npm în runtime | doar în etapa de build | da | recomandat |
|---|
Comenzi și configurări
.npmrc în rădăcina proiectuluiignore-scripts=true
fund=false
audit=false
Instalare reproductibilă, fără scripturinpm ci --omit=dev --ignore-scripts
npm ls --omit=dev --depth=0
Dockerfile multi-stage pentru o aplicație Node.jsFROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build && npm prune --omit=dev
FROM node:22-alpine
WORKDIR /app
USER node
COPY --from=build --chown=node:node /app/dist ./dist
COPY --from=build --chown=node:node /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]
Exemple din practică
Echipă de outsourcing din Chișinău cu client german
Clientul cere lista componentelor și dovada că dependențele nu se schimbă între test și producție. Echipa mută instalarea în GitHub Actions și livrează un artefact cu dist/ și node_modules curățat. Auditul trece fără observații la capitolul dependențe.
Fintech din Chișinău care raportează la BNM
Un dezvoltator rulează npm install pe serverul de raportare pentru un fix urgent. Un pachet tranzitiv actualizat aduce un postinstall care citește variabilele de mediu. Detectarea vine din SIEM, dar rotația tuturor cheilor costă o săptămână.
Greșeli frecvente
- Rulezi npm install --production pe server și crezi că e echivalent cu npm ci: fără lockfile respectat nu e reproductibil, iar scripturile rulează.
- Presupui că --omit=dev elimină riscul supply-chain: chalk și debug erau dependencies, nu devDependencies.
- Păstrezi npm CLI în imaginea finală „pentru depanare” și lași atacatorului un client HTTP cu token.
- Regenerezi package-lock.json pe server când apare un conflict, în loc să repari lockfile-ul în pull request.
Cum te ajută 4hosting
- Orele de DevOps incluse în abonamentul VPS sau dedicat pot muta build-ul în CI/CD; ceri lucrarea din panoul de client, secțiunea Servicii DevOps.
- Hardening & Compliance verifică pipeline-ul, permisiunile și secretele de pe server, cu raport anexabil la contractul cu clientul din UE.
- SIEM & Incident Response corelează logurile de proces, ca un postinstall neașteptat să fie vizibil imediat.
- Suport bilingv română și rusă; facturare în euro cu TVA 20 % defalcat și factură electronică SFS.
Întrebări conexe
Pot păstra devDependencies pe server dacă am nevoie de ele la rulare?
Dacă un pachet este necesar la rulare, locul lui este în dependencies, nu în devDependencies. Mută-l acolo și rebuildează. Excepția reală este un server de dezvoltare, care nu ar trebui să fie accesibil din internet și nu intră în discuția despre producție.
Ce fac dacă un pachet are nevoie de postinstall ca să compileze cod nativ?
Compilează în CI, unde scripturile rulează într-un mediu de unică folosință, și livrează binarul rezultat. Dacă trebuie să rulezi pe server, permite scriptul doar acelui pachet, explicit, și păstrează ignore-scripts=true pentru restul.
Este pnpm sau yarn mai sigur decât npm în privința asta?
Managerul nu schimbă principiul. pnpm blochează implicit scripturile pachetelor din 2025, ceea ce ajută, dar problema de fond rămâne instalarea pe o mașină expusă. Build în CI și artefact promovat sunt recomandarea indiferent de unealtă.