Le moderne squadre di ingegneria stanno sempre più adottando applicazioni Node.js e Next.js in container Docker. Sebbene i container semplifichino la distribuzione del codice, introducono rischi specifici che corrispondono perfettamente alle categorie dell'OWASP Top 10. In questo articolo presentiamo il modello di minaccia, i meccanismi operativi e i passaggi pratici di hardening, affinché le tue immagini Docker soddisfino i requisiti di compliance e i principi del least‑privilege.
Modello di minaccia – cosa può andare storto?
Il vettore di attacco principale contro un container è un'immagine di base configurata in modo errato, contenente pacchetti inutili, account utente predefiniti o porte aperte. Questo tipo di vulnerabilità porta a diverse classi di minacce descritte nell'OWASP Top 10:
- A01 – Broken Access Control: eseguire il processo come root consente l'escalation tramite exploit di librerie di sistema.
- A02 – Cryptographic Failures: assenza di crittografia per variabili d'ambiente e dati sensibili nell'immagine.
- A05 – Security Misconfiguration: impostazioni predefinite del Dockerfile, permessi illimitati sul file system.
Questo modello presuppone che l'attaccante abbia accesso all'immagine (ad es. tramite un registro pubblico) o possa iniettare codice maligno nella fase CI/CD. Perciò ogni fase – dalla costruzione dell'immagine all'esecuzione nel cluster Kubernetes – deve essere soggetta a controllo.
Meccanismo di hardening – come funziona?
L'hardening dei container si basa su tre pilastri: minimalismo dell'immagine, limitazione dei privilegi e monitoraggio continuo delle vulnerabilità. Il minimalismo implica l'uso di immagini base leggere (ad es. node:18‑alpine) e la rimozione di tutti gli strumenti non necessari. La limitazione dei privilegi si realizza definendo un utente non‑root nel Dockerfile e utilizzando le flag --read-only e --cap-drop al momento dell'avvio. Il monitoraggio consiste nella scansione regolare delle immagini con strumenti come Trivy, Anchore o Clair.
Esempio: frammento Dockerfile vulnerabile vs. corretto
# --- DOCKERFILE VULNERABILE ---------------------------------------------------
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]
# esecuzione come root, pieno accesso al file system
Nel esempio sopra l'immagine contiene tutte le dipendenze del progetto, inclusi gli strumenti di sviluppo, e avvia il processo come root – caso classico di A05 – Security Misconfiguration.
# --- DOCKERFILE CORRETTO ----------------------------------------------------
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# ---------- stage finale ----------
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app .
# creazione di un utente non‑root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 3000
# avvio in modalità read‑only, capabilities limitate
CMD ["node", "server.js"]
Nella versione corretta è stato adottato il multi‑stage build, sono state rimosse le dev‑dependencies, è stato definito un utente dedicato e sono stati limitati i privilegi. Questo affronta direttamente A01, A02 e A05.
Checklist di hardening Docker per Node.js / Next.js
- Usa immagini base leggere e ufficiali (alpine, slim).
- Costruzione multi‑stage – separa il layer di build da quello di runtime.
- Installa solo le dipendenze di produzione (
npm ci --only=production). - Definisci un utente non‑root e limita le capabilities (
--cap-drop ALL). - Esegui il container in modalità read‑only, se l'applicazione non richiede scritture.
- Configura i limiti di risorse (CPU, memory) nella podspec di Kubernetes.
- Abilita i profili AppArmor/SELinux e seccomp.
- Esegui scansioni regolari delle immagini per vulnerabilità (OWASP Dependency‑Check, Trivy).
- Utilizza segreti gestiti (Kubernetes Secrets, HashiCorp Vault) – non salvarli mai nell'immagine.
- Audita i log del container e monitora il comportamento dell'applicazione (Falco, OpenTelemetry).
Errori comuni e compromessi
In pratica i team spesso rinunciano a alcune raccomandazioni per comodità. Le trappole più frequenti sono:
- Mantenere l'intera immagine dev in produzione – aumenta la superficie di attacco e porta a A06 (Vulnerable & Outdated Components).
- Mancanza di limitazioni di scrittura – le applicazioni Next.js generano file temporanei; gli sviluppatori spesso disabilitano la modalità read‑only, aprendo la porta al ransomware.
- Utilizzare l'utente root predefinito – il vettore di escalation più semplice, soprattutto in ambienti multi‑tenant.
La soluzione consiste nell’introdurre test di sicurezza automatici nel pipeline CI/CD, che impongono il rispetto dei criteri della checklist. I compromessi devono essere documentati e approvati dal team di sicurezza.
Riferimenti agli standard
Le nostre raccomandazioni si basano su framework riconosciuti:
- OWASP Top 10 – classificazione delle minacce più importanti per le applicazioni web.
- CWE‑250 – limitazione dei privilegi (principio del minimo privilegio).
- Docker Bench for Security – set di test conforme al CIS Docker Benchmark.
- Kubernetes Hardening Guide – best practice per pod e cluster.
«La sicurezza dei container non è una configurazione una tantum, ma un processo continuo di verifica e miglioramento.»
Esempio pratico di implementazione in CI/CD
Di seguito lo schema di un semplice pipeline in GitHub Actions, che costruisce, scansiona e pubblica l’immagine:
name: Build & Secure Docker Image
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build image
run: |
docker build -t myapp:${{ github.sha }} .
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
exit-code: '1'
ignore-unfixed: true
- name: Push to registry
if: success()
run: |
echo ${{ secrets.REGISTRY_PASSWORD }} | docker login -u ${{ secrets.REGISTRY_USER }} --password-stdin
docker push myapp:${{ github.sha }}
Il pipeline impone che ogni modifica al codice debba superare la scansione delle vulnerabilità prima della pubblicazione dell’immagine, riducendo il rischio di introdurre una vulnerabilità di tipo A06.
In sintesi, l’hardening dei container Docker per applicazioni Node.js e Next.js richiede un approccio consapevole alla riduzione dell’immagine, all’adozione del principio del minimo privilegio e al monitoraggio continuo. L’utilizzo della checklist sopra e l’integrazione della scansione nel CI/CD consentono di eliminare efficacemente i rischi dell’OWASP Top 10. Se hai bisogno di supporto per implementare queste pratiche nella tua organizzazione, contatta Coderia.it – ti aiuteremo a costruire un’infrastruttura container sicura e scalabile.



