06 - Securitatea lanțului de aprovizionare: audit npm, SBOM și managementul dependențelor
Septembrie 2025 a marcat un punct de cotitură în istoria securității software: optsprezece pachete npm printre cele mai descărcate din lume, inclusiv cretă, depanare e ansi-stiluri, sunt compromise printr-o campanie de phishing care vizează întreținerii. În doar câteva ore, peste 2,6 miliarde de descărcări săptămânale sunt expuse codului JavaScript ofuscat conceput pentru a intercepta tranzacțiile cu criptomonede. Acesta nu este un atac la aplicația dvs., ci la ecosistemul care o susține.
Acest scenariu ilustrează natura fundamentală a atacurilor lanțului de aprovizionare: nu vizează
codul pe care îl scrieți, dar codul în care aveți încredere. Fiecare dependență cu care instalați
npm install reprezintă cod scris de alții, întreținut de alții și, eventual
compromisă de alții. Într-un proiect Node.js de dimensiuni medii, dependențele directe sunt
de obicei, 20-50 de pachete, dar graficul de dependență tranzitiv complet poate ajunge
cu ușurință cele 500-1000 de biblioteci. Chiar verifici tot acest cod?
Conform OWASP Top 10:2025, categoria A03: Eșecuri de integritate software și date include în mod explicit eșecurile lanțului de aprovizionare ca vector critic. Acesta este unul dintre cei doi noi categorii introduse în ediția din 2025, o recunoaștere explicită că siguranța codul nu mai poate ignora siguranța dependențelor. Acest articol vă oferă instrumentele concrete pentru a vă proteja.
Ce vei învăța
- Anatomia unui atac al lanțului de aprovizionare: typosquatting, confuzie de dependență, otrăvire a fișierelor de blocare
- audit npm, audit al firelor, audit pnpm: utilizare avansată și automatizare
- Integritatea fișierului de blocare și verificarea hash cu npm ci
- SBOM: generație cu CycloneDX și SPDX, standard NTIA
- Snyk și Dependabot: monitorizare continuă a vulnerabilității
- Întărirea acțiunilor GitHub: fixare SHA și permisiuni minime
- Securitatea imaginii containerului: Trivy, Syft și semnați cu Cosign/Sigstore
- Confuzia de dependență și cum să vă apărați împotriva domeniilor private npm
Anatomia unui atac al lanțului de aprovizionare
Înțelegerea modului în care funcționează atacurile lanțului de aprovizionare este primul pas în a vă apăra. Există mai multe categorii principale, fiecare cu caracteristici distincte și vectori de atac.
Typosquatting: pericolul unei greșeli de tipar
Typosquatting exploatează erorile comune de tastare. Un atacator publică
lodahs (în loc de lodash), requst (în loc de
request), sau colerrs (în loc de colors). În 2025,
Cercetătorii de securitate au identificat un set de pachete typosquat concepute pentru
imita biblioteci populare care au lansat terminale ascunse prin intermediul scripturilor postinstall
pentru a exfiltra în tăcere acreditările.
Principala apărare este verificarea temeinică a numelui înainte de a instala orice pachet. Instrumente precum Snyk și Socket.dev analizează automat numele pentru similitudine pachetele existente și raportați eventualele erori de tipar înainte de instalare.
Confuzie de dependență: domeniu public vs privat
Confuzia de dependență (sau confuzia spațiului de nume) este un atac mai sofisticat documentat pentru prima dată de Alex Birsan în 2021. Atacatorul publică un pachet pe npm cu același nume ca un pachet intern privat al companiei țintă, dar cu un număr de versiune superioară. npm, în mod implicit, rezolvă cea mai recentă versiune din registrul public, conducând pachetul rău intenționat să îl înlocuiască pe cel legitim.
Caz real: confuzie de dependență la scară largă
În 2021, Alex Birsan a compromis peste 35 de companii majore, inclusiv Microsoft, Apple, PayPal și Shopify folosind această tehnică, câștigând mai mult de 130.000 USD în recompense pentru erori. Mecanismul a fost simplu: găsiți numele pachetelor interne în fișierele de configurare public (package.json, pyproject.toml) și publicați-le cu versiunea 9.9.9 în registrele publice.
Preluarea contului de întreținere
Cel mai insidios atac din 2025 a demonstrat cât de phishing este adresat întreținătorilor a devenit transportatorul preferat. Odată ce contul unui întreținător legitim este compromis, atacatorul publică versiuni rău intenționate ale pachetelor deja de încredere. Comunitatea are încredere a pachetului, testele de securitate trec, iar codul rău intenționat intră în producție.
Intoxicare cu fișier de blocare
Într-un atac de otrăvire a fișierelor de blocare, un contribuitor rău intenționat modifică direct fișierul
package-lock.json o yarn.lock într-o cerere de tragere spre a indica
versiuni compromise sau hashuri diferite de cele așteptate. Dacă procesul de revizuire nu include
verificând fișierul de blocare, codul rău intenționat trece neobservat.
npm audit: Utilizare avansată
npm audit și punctul de plecare, dar utilizarea corectă necesită mai mult decât
o execuție simplă. Să vedem cum să-l integrăm eficient în fluxul de lucru de dezvoltare.
# Audit base con output JSON per processing automatico
npm audit --json
# Audit solo production dependencies (esclude devDependencies)
npm audit --omit=dev
# Fissa automaticamente le vulnerabilità patchabili
npm audit fix
# Fix anche di breaking changes (usare con cautela)
npm audit fix --force
# Audit con soglia di severita: exit code 1 se ci sono critical
npm audit --audit-level=critical
# Audit con soglia moderate
npm audit --audit-level=moderate
# Output in formato per CI/CD
npm audit --json | jq '.metadata.vulnerabilities'
Pentru un proiect cu multe dependențe, numărul de vulnerabilități poate fi mare și
greu de gestionat. O strategie eficientă este configurarea unui fișier .npmrc
cu politicile de audit ale proiectului sau utilizarea npm audit cu un dosar
configurație de excepție.
# .nsprc (Node Security Project configuration)
# Oppure usa audit-resolve.json con npm-audit-resolver
# Installazione di npm-audit-resolver per gestire eccezioni
npm install -g npm-audit-resolver
# Processo interattivo per gestire ogni vulnerabilità
audit-resolve
# Verifica successiva (usa le eccezioni salvate)
audit-resolve --ci
# Script package.json per CI sicuro
# package.json
{
"scripts": {
"audit:ci": "npm audit --audit-level=high --omit=dev",
"audit:full": "npm audit --json > audit-report.json",
"audit:check": "npm audit --audit-level=critical"
}
}
auditul pnpm și auditul firelor
Dacă utilizați pnpm sau yarn, comenzile de audit sunt similare, dar cu unele diferențe importante. pnpm oferă un control mai granular asupra dependențelor, în timp ce yarn v2/v3 (Berry) o face gestionarea hashului îmbunătățită semnificativ.
# pnpm audit
pnpm audit
pnpm audit --audit-level high
pnpm audit --prod # solo production
# yarn audit (classic v1)
yarn audit
yarn audit --level high
# yarn audit (Berry v2/v3)
yarn npm audit
yarn npm audit --severity high
# Output JSON per processing
pnpm audit --json | jq '.advisories | length'
Integritatea fișierului de blocare: Prima linie de apărare
Fișierul de blocare (package-lock.json, yarn.lock, pnpm-lock.yaml)
și critic pentru reproductibilitatea și securitatea construcției. Fiecare intrare din fișierul de blocare
include nu numai versiunea exactă, ci și hash-ul conținutului pachetului.
npm ci vs npm install: o distincție critică
În producție și CI/CD, folosiți întotdeauna npm ci în loc de npm install.
npm ci instalați exact versiunile specificate în fișierul de blocare, verificați
hashe-urile criptografice ale fiecărui pachet și eșuează dacă fișierul de blocare nu este sincronizat cu
pachetul.json. npm install poate actualiza fișierul de blocare în tăcere.
# CORRETTO per CI/CD: verifica integrita lockfile
npm ci
# Verifica manuale degli hash nel lockfile
# package-lock.json contiene entries come:
# "node_modules/lodash": {
# "version": "4.17.21",
# "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
# "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZboqV76wE2wDvQ6",
# }
# Verifica che il lockfile non sia stato modificato
git diff package-lock.json | head -50
# Pre-commit hook per prevenire modifiche non autorizzate al lockfile
# .husky/pre-commit
#!/bin/sh
if git diff --cached --name-only | grep -q "package-lock.json"; then
echo "WARNING: package-lock.json modificato. Verifica le dipendenze."
npm audit --audit-level=high
fi
Configurare .npmrc pentru securitate
Dosarul .npmrc vă permite să configurați npm cu politicile de securitate pe care dvs
se aplică întregului proiect sau utilizatorului actual.
# .npmrc - configurazione sicurezza progetto
# Richiedi sempre HTTPS per il registro
registry=https://registry.npmjs.org/
# Abilita strict-ssl (default: true, non disabilitare mai!)
strict-ssl=true
# Audit automatico dopo ogni install
audit=true
# Fund messages: disabilita per CI
fund=false
# Usa lockfile (default: true)
package-lock=true
# Per workspace con pacchetti privati su registro Artifactory/Nexus
# @mycompany:registry=https://npm.mycompany.internal/
# //npm.mycompany.internal/:_authToken={NPM_TOKEN}
# Prevenzione dependency confusion: scope sempre sul registro privato
# @internal:registry=https://npm.internal.company.com/
Confuzie de dependență: Apărarea cu domenii private
Cea mai eficientă apărare împotriva confuziei de dependență este să vă asigurați că pachetele sunt private utilizați întotdeauna un domeniu dedicat și acel npm este configurat pentru a rezolva acel domeniu exclusiv din registrul intern.
# package.json con scope privato corretto
{
"dependencies": {
"@mycompany/auth-utils": "^2.1.0",
"@mycompany/api-client": "^1.5.0"
}
}
# .npmrc - scope privati sempre sul registro interno
@mycompany:registry=https://npm.mycompany.internal/
//npm.mycompany.internal/:_authToken=${INTERNAL_NPM_TOKEN}
# Verifica che un pacchetto @mycompany NON esista su npm pubblico
npm view @mycompany/auth-utils --registry https://registry.npmjs.org/
# Deve restituire 404 - se restituisce un pacchetto, qualcuno ha fatto typosquatting!
# GitHub Actions: verifica automatica assenza pacchetti privati su npm pubblico
# - name: Check private packages not on public npm
# run: |
# for pkg in $(cat package.json | jq -r '.dependencies | keys[]' | grep "^@mycompany"); do
# if npm view $pkg --registry https://registry.npmjs.org/ 2>/dev/null; then
# echo "ALERT: $pkg trovato su npm pubblico!" && exit 1
# fi
# done
SBOM: Lista materialelor software
O listă de materiale software (SBOM) și un inventar complet și formal al tuturor componentelor software într-o aplicație: biblioteci terțe, dependențe tranzitive, versiuni, licențe și vulnerabilități cunoscute. A devenit o cerință de facto pentru securitatea întreprinderii și, în unele sectoare (guvernul SUA, infrastructură critică), este cerut de lege.
Cele două standarde principale sunt SPDX (Schimb de date pachet software, Linux Foundation) e CycloneDX (OWASP). SPDX este orientat spre conformitatea licenței, CycloneDX este optimizat pentru managementul securității și vulnerabilităților. Pentru aplicații web, CycloneDX este, în general, cea mai bună alegere.
De ce este important SBOM
Proiectele care utilizează SBOM pentru a gestiona dependențele obțin o reducere de 264 de zile în Mean Time to Remediate (MTTR) pentru vulnerabilități critice în comparație cu cele fără SBOM. În cazul unui nou CVE (cum ar fi Log4Shell), SBOM permite identificarea în câteva minute toate proiectele afectate în loc de săptămâni de analiză manuală.
Generarea SBOM cu CycloneDX
# Installazione CycloneDX CLI per Node.js
npm install -g @cyclonedx/cyclonedx-npm
# Generazione SBOM in formato JSON (CycloneDX v1.6)
cyclonedx-npm --output-format json --output-file sbom.json
# Generazione SBOM in formato XML
cyclonedx-npm --output-format xml --output-file sbom.xml
# Con dipendenze di sviluppo escluse
cyclonedx-npm --omit dev --output-format json --output-file sbom-prod.json
# Verifica del SBOM generato
cat sbom.json | jq '.metadata.component.name'
cat sbom.json | jq '.components | length'
cat sbom.json | jq '.vulnerabilities | length'
# Esempio output SBOM JSON (struttura CycloneDX v1.6)
# {
# "bomFormat": "CycloneDX",
# "specVersion": "1.6",
# "serialNumber": "urn:uuid:1a2b3c4d-...",
# "version": 1,
# "metadata": {
# "timestamp": "2026-02-25T10:30:00Z",
# "tools": [...],
# "component": {
# "type": "application",
# "name": "my-app",
# "version": "1.0.0"
# }
# },
# "components": [
# {
# "type": "library",
# "name": "express",
# "version": "4.18.2",
# "purl": "pkg:npm/express@4.18.2",
# "hashes": [
# { "alg": "SHA-256", "content": "abc123..." }
# ],
# "licenses": [{ "license": { "id": "MIT" } }]
# }
# ]
# }
Generarea SBOM cu Syft
Syft by Anchore este unul dintre cele mai complete instrumente pentru generarea de SBOM, cu suport pentru imagini container, sisteme de fișiere și artefacte npm/pip/go/java.
# Installazione Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# SBOM da directory progetto (formato CycloneDX JSON)
syft dir:. -o cyclonedx-json=sbom.json
# SBOM da container image
syft nginx:latest -o spdx-json=sbom-nginx.json
# SBOM da immagine locale Docker
syft docker:my-app:latest -o cyclonedx-json=sbom.json
# Output in più formati simultaneamente
syft dir:. \
-o cyclonedx-json=sbom-cdx.json \
-o spdx-json=sbom-spdx.json \
-o table
# Filtrare solo componenti npm
syft dir:. -o cyclonedx-json | jq '.components[] | select(.purl | startswith("pkg:npm"))'
Snyk și Dependabot: Monitorizare continuă
Monitorizarea unică nu este suficientă: sunt descoperite noi vulnerabilități în fiecare zi. Snyk și GitHub Dependabot oferă monitorizare continuă cu alerte automate și actualizați solicitările de extragere.
Snyk CLI și integrare
# Installazione Snyk CLI
npm install -g snyk
# Autenticazione
snyk auth
# Test vulnerabilità progetto
snyk test
# Test con soglia: exit 1 se vulnerabilità high/critical
snyk test --severity-threshold=high
# Monitor continuo (invia snapshot a Snyk dashboard)
snyk monitor
# Fix automatico con patch
snyk fix
# Generazione report HTML
snyk test --json | snyk-to-html -o report.html
# Test container image
snyk container test nginx:latest --severity-threshold=high
# Generazione SBOM via Snyk
snyk sbom --format cyclonedx1.6+json
# Integrazione in package.json
# {
# "scripts": {
# "security:test": "snyk test --severity-threshold=high",
# "security:monitor": "snyk monitor",
# "security:container": "snyk container test $IMAGE_NAME"
# }
# }
GitHub Dependabot: Configurație optimă
# .github/dependabot.yml
version: 2
updates:
# npm/Node.js dependencies
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Europe/Rome"
open-pull-requests-limit: 10
# Raggruppa aggiornamenti di patch e minor
groups:
production-dependencies:
dependency-type: "production"
update-types:
- "minor"
- "patch"
dev-dependencies:
dependency-type: "development"
update-types:
- "minor"
- "patch"
# Label automatiche per PR
labels:
- "dependencies"
- "security"
# Revisori automatici
reviewers:
- "security-team"
# Ignora major updates di alcune librerie critiche
ignore:
- dependency-name: "webpack"
update-types: ["version-update:semver-major"]
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
Securitate GitHub Actions: SHA-Pinning și Hardening
Acțiunile GitHub reprezintă un vector critic de atac pe lanțul de aprovizionare.
În 2024, compromisul de tj-actions/changed-files a demonstrat cum
o acțiune utilizată pe scară largă poate fi compromisă și folosită pentru a exfiltra secrete din
mii de depozite. Principala apărare și SHA-pinning: în loc de referință
o acțiune per etichetă (@v4), este folosit hash-ul imuabil al commit-ului.
# .github/workflows/security-ci.yml
name: Security CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
# Permissions minime (principio del minimo privilegio)
permissions:
contents: read
security-events: write # Per upload SARIF a GitHub Security tab
jobs:
dependency-audit:
name: Dependency Security Audit
runs-on: ubuntu-latest
permissions:
contents: read
steps:
# SHA-pinned: usa hash commit, non tag!
# actions/checkout@v4 -> SHA esatto del commit
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '22'
cache: 'npm'
# Usa npm ci (non npm install) per verifica lockfile
- name: Install dependencies (strict lockfile)
run: npm ci --ignore-scripts
# Audit con exit code per bloccare la build
- name: npm audit
run: npm audit --audit-level=high --omit=dev
# Snyk test (richiede SNYK_TOKEN secret)
- name: Snyk Security Test
uses: snyk/actions/node@b98d498629f1c5e3943f89a5c62b5e5d4e2f86c0 # SHA pinned
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high --fail-on=upgradable
sbom-generation:
name: Generate SBOM
runs-on: ubuntu-latest
needs: dependency-audit
permissions:
contents: write
id-token: write # Per OIDC (Sigstore)
attestations: write
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '22'
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Generate SBOM (CycloneDX)
run: |
npm install -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --omit dev --output-format json --output-file sbom.json
# Attesta il SBOM con OIDC (GitHub native attestation)
- name: Attest SBOM
uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3
with:
subject-path: sbom.json
- name: Upload SBOM as artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.0
with:
name: sbom
path: sbom.json
Anti-Pattern: nu utilizați niciodată etichete în acțiunile terțelor părți
uses: some-org/some-action@v2 și vulnerabil: dacă contul de întreținere
este compromisă, eticheta poate fi actualizată pentru a indica cod rău intenționat.
Folosiți întotdeauna formatul uses: some-org/some-action@SHA_HASH # v2.0.0
și includeți eticheta ca comentariu pentru lizibilitate. Instrumente ca
pinact e action-pins automatiza acest proces.
Permisiuni minime în fluxul de lucru
# Imposta permissions di default a read-only per tutto il workflow
# SEMPRE aggiungere questo al livello top del workflow
permissions:
contents: read
# Poi concedi permissions aggiuntive solo ai job che le necessitano
jobs:
build:
permissions:
contents: read
packages: write # Solo se deve pubblicare su GitHub Packages
# Esempio job che NON ha bisogno di scrivere
test:
permissions:
contents: read # Solo lettura
# Variabili d'ambiente: mai hardcodare secrets
# SBAGLIATO:
# env:
# API_KEY: "sk-prod-abc123"
# CORRETTO: usa sempre GitHub Secrets
# env:
# API_KEY: ${{ secrets.API_KEY }}
# Limita anche GITHUB_TOKEN
# SBAGLIATO: permissions non specificati (default read+write)
# CORRETTO: specifica esplicitamente il minimo necessario
Container Image Security
Dacă aplicația dvs. este implementată în containere Docker, suprafața de atac include, de asemenea, imaginea de bază și pachetele OS instalate. Trivy și Grype sunt instrumente principale pentru scanarea vulnerabilităților din imaginile containerului.
# Installazione Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Scansione immagine locale
trivy image my-app:latest
# Solo vulnerabilità CRITICAL e HIGH
trivy image --severity HIGH,CRITICAL my-app:latest
# Output in formato SARIF per GitHub Security tab
trivy image --format sarif --output trivy-results.sarif my-app:latest
# Scansione del filesystem (anche senza Docker)
trivy fs --scanners vuln,secret,misconfig .
# Scansione con SBOM output
trivy image --format cyclonedx --output sbom.json my-app:latest
# Dockerfile best practices: usa immagini distroless
# FROM node:22-alpine AS builder
# WORKDIR /app
# COPY package*.json ./
# RUN npm ci --omit=dev
# COPY . .
# RUN npm run build
# Usa distroless come runtime (superficie minima di attacco)
# FROM gcr.io/distroless/nodejs22-debian12
# COPY --from=builder /app/dist /app
# EXPOSE 3000
# CMD ["/app/server.js"]
# Firma immagine con Cosign/Sigstore
cosign sign --yes my-registry/my-app:latest
# Verifica firma
cosign verify my-registry/my-app:latest --certificate-identity-regexp=".*" --certificate-oidc-issuer="https://accounts.google.com"
Lista de verificare unghiulară: securitatea lanțului de aprovizionare
Pentru proiectele Angular, există considerații specifice pentru lanțul de instrumente (Angular CLI, webpack/esbuild, ng-packagr) și ecosistemul npm.
# Angular Supply Chain Security Checklist
# 1. Verifica la versione di Angular CLI e dipendenze
ng version
npm audit
# 2. Aggiorna Angular alla versione LTS più recente
ng update @angular/core @angular/cli
# 3. Controlla i peer dependencies
npm ls --depth=0
# 4. Identifica dipendenze deprecate
npm outdated
# 5. Usa npm ci in tutti i CI/CD pipeline Angular
npm ci
# 6. Verifica integrità del lockfile prima di ogni build
git diff package-lock.json
# 7. Configura angular.json per production build con source-map disabilitato
# angular.json
# "configurations": {
# "production": {
# "sourceMap": false,
# "optimization": true,
# "buildOptimizer": true
# }
# }
# 8. Scansiona le dipendenze Angular specifiche
snyk test --file=package.json
# 9. Genera SBOM del progetto Angular
cyclonedx-npm --output-format json --output-file sbom-angular.json
# 10. Aggiungi Content-Security-Policy nel server Angular SSR
# Per Express server in server.ts:
# app.use((req, res, next) => {
# res.setHeader('Content-Security-Policy',
# "default-src 'self'; script-src 'self'");
# next();
# });
Flux de lucru complet: Poarta de securitate în CI/CD
Integrarea tuturor acestor instrumente într-o poartă de securitate coerentă asigură că niciuna build ajunge la producție fără a trece de verificările de securitate a lanțului de aprovizionare.
# .github/workflows/supply-chain-security.yml
name: Supply Chain Security Gate
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Esegui ogni giorno alle 6:00 UTC per monitoraggio continuo
- cron: '0 6 * * *'
permissions:
contents: read
security-events: write
jobs:
security-gate:
name: Supply Chain Security Gate
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '22'
cache: 'npm'
# Verifica integrita lockfile
- name: Verify lockfile integrity
run: |
if [ ! -f "package-lock.json" ]; then
echo "ERROR: package-lock.json mancante!" && exit 1
fi
npm ci --ignore-scripts
# Audit npm - blocca su HIGH/CRITICAL
- name: npm audit (production)
run: npm audit --audit-level=high --omit=dev
continue-on-error: false
# Snyk test
- name: Snyk vulnerability scan
uses: snyk/actions/node@b98d498629f1c5e3943f89a5c62b5e5d4e2f86c0
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high --sarif-file-output=snyk.sarif
# Upload risultati a GitHub Security tab
- name: Upload Snyk results to GitHub Security
uses: github/codeql-action/upload-sarif@dd746615b1a4b1e1c5d3b87432fe040f4c04082 # v3.28.0
with:
sarif_file: snyk.sarif
# Genera SBOM
- name: Generate SBOM
run: |
npm install -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --omit dev \
--output-format json \
--output-file sbom-${{ github.sha }}.json
# Salva SBOM come artifact
- name: Archive SBOM
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.0
with:
name: sbom-${{ github.sha }}
path: sbom-${{ github.sha }}.json
retention-days: 90
# License check
- name: Check licenses
run: |
npx license-checker --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;0BSD' \
--excludeDevDependencies \
--json > licenses.json || {
echo "ALERT: Licenze non conformi trovate!"
cat licenses.json
exit 1
}
Citat de detectare a typosquatting
Înainte de a instala orice pachet nou, este o practică bună să-l testați cu instrumente de analize dedicate. Socket.dev este unul dintre cele mai bune instrumente de analiză a securității a unui pachet npm înainte de instalare.
# Socket.dev CLI per analisi preventiva
npm install -g @socketsecurity/cli
# Analizza un pacchetto prima di installarlo
socket npm info lodash
# Scansione del progetto esistente
socket scan create --view
# npm-check per pacchetti outdated e typosquatting
npm install -g npm-check
npm-check
# Verifica manuale: controlla chi ha pubblicato il pacchetto
npm view express maintainers
npm view express time # storia delle pubblicazioni
# Red flags da cercare:
# - Pacchetto pubblicato pochi giorni fa con molti download
# - Maintainer con storia breve
# - Nessuna homepage o repository
# - Scripts postinstall/preinstall sospetti
# Verifica scripts nel package.json della dipendenza
npm view lodash scripts
# Installa senza eseguire lifecycle scripts (postinstall, preinstall)
npm install --ignore-scripts
# Verifica il contenuto del pacchetto prima di usarlo
npm pack lodash --dry-run
Steaguri roșii în pachetele npm
- Script post-instalare: Rulați codul la instalare
- Acces la variabilele de mediu:
process.envîntr-un pachet care nu ar trebui să aibă nevoie de el - Solicitări HTTP către domenii necunoscute: Niciun pachet UI nu ar trebui să efectueze apeluri de rețea în momentul instalării
- Dependențe native (legături): Compilați codul C/C++ cu acces la sistem
- Versiunea 0.0.1 cu 10 milioane de descărcări: imposibil, semnal de manipulare statistică
- Nume similar cu pachetele celebre: Verificați întotdeauna npm.im înainte de a instala
Concluzii și pașii următori
Securitatea lanțului de aprovizionare nu este o activitate unică, ci un proces continuu. 2025 a demonstrat că chiar și cele mai de încredere pachete pot fi compromise și că apărarea trebuie să fie stratificată: verificarea fișierelor de blocare, audituri automate, SBOM-uri generate cu fiecare lansare, acțiuni GitHub cu fixare SHA și monitorizare continuă cu Snyk sau Dependabot.
Începeți cu cei mai simpli pași: adăugați npm audit --audit-level=high la a ta
CI/CD, folosiți întotdeauna npm ci în loc de npm install în conducte,
și activați Dependabot în depozitul dvs. Aceste trei modificări acoperă majoritatea
de vectori de atac cu investiții minime de timp.
Următorul pas este generarea SBOM la fiecare lansare și implementare o poartă de securitate completă precum cea prezentată în acest articol. Cu aprovizionare OWASP A03 Eșecuri în lanț acum oficial în Top 10 2025, acesta nu mai este un lucru plăcut: și o responsabilitate profesională a fiecărui dezvoltator.
Seria continuă: Web Security for Developers
- 01 - OWASP Top 10 2025: Ghid pentru dezvoltatori
- 02 - XSS, CSRF și CSP: Securitate Frontend
- 03 - Injecție SQL și validare a intrărilor: Securitate backend
- 04 - Autentificare sigură: sesiune și cookie-uri
- 05 - Securitate API: OAuth 2.1, JWT și Rate Limiting
- 06 - Securitatea lanțului de aprovizionare: audit npm și SBOM (acest articol)
- 07 - Erori criptografice: hashing, criptare și token
- 08 - DevSecOps pentru dezvoltatori: SAST, DAST în CI/CD
Aflați și mai multe despre serie Frontend DevOps (ID-uri 250-255) pentru a integra securitatea în fluxul dvs. de lucru de implementare.







