Passa al contenuto

Sicurezza dei container: 12 errori da evitare prima del deployment

30 agosto 2026 di
Sicurezza dei container: 12 errori da evitare prima del deployment
Digital Lab srl

Sicurezza dei container: 12 errori da evitare prima del deployment

I container hanno semplificato il ciclo di vita delle applicazioni: build riproducibili, deployment rapidi, portabilità tra ambienti. Ma la stessa tecnologia che accelera il software introduce una superficie d'attacco nuova, spesso sottovalutata. Un container mal configurato non è un problema solo tecnico: in un'architettura moderna può diventare il punto di ingresso per un attaccante che punta all'intero cluster o all'host.

Questa guida raccoglie i dodici errori più frequenti che abbiamo osservato nei progetti di migrazione e sviluppo containerizzato, allineandosi alle raccomandazioni dell'OWASP Docker Security Cheat Sheet e della guida NIST SP 800-190 (Application Container Security Guide), verificate alla data di redazione (30 agosto 2026). Correggerli prima del deployment non richiede strumenti esoterici: richiede disciplina, processi chiari e qualche controllo sistematico.

Il contesto: i container condividono il kernel dell'host

Prima di entrare negli errori, un dato di contesto che spiega perché la sicurezza dei container è diversa da quella di una VM. I container non contengono un sistema operativo completo: condividono il kernel dell'host. Questo significa che una vulnerabilità del kernel o del runtime non resta confinata: può trasformarsi in un container escape e dare all'attaccante accesso root sull'host.

L'OWASP cita esempi concreti: la vulnerabilità nota come Leaky Vessels (CVE-2024-21626, nel runtime runc) permetteva di uscire dal container sfruttando la directory di lavoro del processo; l'exploit di privilege escalation del kernel Dirty COW, eseguito dentro un container anche ben isolato, poteva comunque portare a root sull'host vulnerabile. Da qui la prima regola, trasversale a tutte le altre: host e Docker Engine vanno aggiornati con continuità, perché il livello di sicurezza dei tuoi container non può superare quello del kernel che condividono.

I 12 errori

1. Immagine base non affidabile e tag latest

Partire da un'immagine enorme, con librerie inutili o — peggio — da un'immagine non ufficiale di un registro pubblico significa ereditare un'intera superficie d'attacco senza rendersene conto. L'OWASP raccomanda di verificare provenienza e manutentore dell'immagine e di usare una tag specifica e immutabile invece di latest: una tag flottante cambia nel tempo, rendendo le build non riproducibili e i controlli di sicurezza impossibili da ripetere.

Preferisci distribuzioni minimali e immagini ufficiali, e traccia la provenienza di ogni artefatto: la generazione di una Software Bill of Materials (SBOM) e la firma digitale delle immagini (image signing) sono ormai pratiche standard per la supply chain, come indicato nell'OWASP alla regola sulla sicurezza della catena di fornitura.

2. Immagini mai scansionate per vulnerabilità

Costruire l'immagine e dichiararla "pronta" senza averla mai scansionata è tra gli errori più diffusi. Le vulnerabilità note delle librerie open source vengono scoperte ogni settimana e molte hanno exploit pubblici già disponibili. La scansione deve essere parte integrante della pipeline CI/CD, non un controllo manuale saltuario: strumenti come Trivy, Grype, Snyk e Docker Scout si integrano nei flussi di lavoro e possono bloccare la build quando il livello di rischio supera la soglia accettabile.

Lo stesso vale per il Dockerfile: un linter di sicurezza eseguito in pipeline (ad esempio Docker Bench for Security o le baseline dev-sec.io) intercetta problemi che la scansione delle immagini non vede, come l'assenza della direttiva USER, versioni non pinnate dei pacchetti di sistema o l'uso di ADD al posto di COPY.

3. Container eseguiti come root

Di default, i processi dentro un container girano con l'utente root. Se l'attaccante compromette l'applicazione, ottiene di fatto i privilegi massimi dentro il container, e da lì la strada verso il kernel e l'host si accorcia. L'OWASP indica tre modi per correggere:

  • al runtime, con docker run -u 4000;
  • in build, creando un utente dedicato nel Dockerfile e impostandolo con USER;
  • a livello di daemon, abilitando il remapping degli user namespace (--userns-remap=default).

In Kubernetes lo stesso controllo si fa con il campo runAsUser del Security Context. Non è un dettaglio: è la prima linea di difesa contro l'escalation dei privilegi.

4. Flag --privileged e capabilities eccessive

Linux capabilities sono i privilegi granulari che il kernel concede ai processi. Docker di default ne abilita solo un sottoinsieme, ma il flag --privileged li aggiunge tutti: di fatto il container si comporta come se girasse a livello di host. La configurazione più sicura, come raccomanda l'OWASP, è partire dal minimo:

docker run --cap-drop all --cap-add CHOWN myimage

Elimina tutte le capabilities e aggiungi solo quelle strettamente necessarie al workload. In Kubernetes il controllo equivalente passa dal campo capabilities del Security Context, con drop: [ALL] e l'elenco esplicito delle sole capability richieste.

5. Escalation dei privilegi interna non bloccata

Anche se il container gira con un utente non privilegiato, un binario con il bit setuid o setgid può tentare di alzare i privilegi. L'opzione --security-opt=no-new-privileges impedisce al processo di acquisire nuovi privilegi, ed è raccomandata dall'OWASP per ogni workload. In Kubernetes si traduce in allowPrivilegeEscalation: false nel Security Context. Costa zero, si applica ovunque e chiude un'intera classe di attacchi.

6. Socket del daemon esposto dentro i container

/var/run/docker.sock è la porta d'accesso alla Docker API, di proprietà di root: chi ha accesso al socket ha di fatto accesso root all'host. Montarlo dentro un container (-v /var/run/docker.sock:/var/run/docker.sock) consegna quel potere a qualunque processo compromesso al suo interno. L'OWASP è netto: non esporre mai il socket, nemmeno in sola lettura — il read-only lo rende solo più difficile da sfruttare, non sicuro. Va evitato anche l'ascolto del daemon su socket TCP non protetto (-H tcp://0.0.0.0:...), che su un host esposto equivale a un root service pubblico.

7. Filesystem e volumi scrivibili

Un'applicazione che non deve scrivere sul proprio filesystem non dovrebbe poterlo fare: se l'attaccante compromette il processo, ogni directory scrivibile è un posto dove depositare payload e manomettere file. L'OWASP raccomanda di eseguire i container con filesystem in sola lettura (--read-only) e, dove serve spazio temporaneo, combinarlo con un tmpfs:

docker run --read-only --tmpfs /tmp myimage

I volumi montati solo per lettura vanno dichiarati tali (:ro). In Kubernetes, readOnlyRootFilesystem: true nel Security Context dà lo stesso risultato.

8. Risorse illimitate

Senza limiti di memoria, CPU, processi e file descriptor, un workload compromesso — o semplicemente mal implementato — può esaurire le risorse dell'host e trasformarsi in un denial of service per tutto ciò che ci gira accanto. L'OWASP consiglia di limitare memoria, CPU, numero massimo di restart (--restart=on-failure:<n>), file descriptor e processi via --ulimit. I limiti vanno definiti in fase di deployment, non dopo un incidente.

9. Comunicazione inter-container aperta

Di default tutti i container della stessa rete condividono la comunicazione: se una rete piatta collega tutto, una singola compromissione diventa il trampolino per muoversi lateralmente. Invece di affidarsi alla rete piatta di default, l'OWASP consiglia di creare reti Docker dedicate e di collegare a ciascuna solo i container che devono parlarsi. In Kubernetes si applica lo stesso principio con le Network Policy, che regolano esplicitamente quali pod possono comunicare tra loro.

10. Porte pubblicate su tutte le interfacce

Un malinteso frequente riguarda i firewall host: chi usa UFW dà per scontato che le sue regole proteggano anche il traffico verso i container. Non è così: Docker gestisce direttamente le proprie regole iptables e nftables, aggirando UFW. Quando pubblichi una porta con -p 8000:8000, Docker apre quella porta su tutte le interfacce e tutti gli indirizzi sorgente, potenzialmente prima delle regole DENY esplicite.

La mitigazione semplice è vincolare il binding a localhost:

docker run -p 127.0.0.1:8000:8000 myimage

E, per chi ha bisogno di regole di firewall più fini, esistono integrazioni (come ufw-docker) che fanno rispettare a Docker le policy UFW.

11. Secret dentro le immagini o nelle variabili d'ambiente

Password, token e chiavi SSH finiscono nelle immagini più spesso di quanto si creda: copiati in fase di build, incorporati nei layer, passati come variabili d'ambiente visibili a chiunque ispezioni il container. L'OWASP raccomanda di gestire i dati sensibili con Docker Secrets, che li rendono disponibili ai servizi senza incorporarli nell'immagine. Attenzione però al contesto: in Kubernetes i secret di default non sono cifrati a riposo, quindi servono misure aggiuntive come la cifratura di etcd o strumenti dedicati. La regola di base resta: mai secret in immagine, mai secret nei log, mai secret in chiaro nelle variabili d'ambiente.

12. Profili di sicurezza runtime disattivati e host non aggiornati

Docker applica di default profili di sicurezza del runtime: seccomp limita le syscall, AppArmor e SELinux applicano controllo degli accessi obbligatorio. Disattivarli "perché rallentano" o "perché danno problemi" elimina uno strato di difesa prezioso. L'OWASP è esplicito: partire sempre dal profilo di default e personalizzarlo per workload, mai rimuoverlo. Il monitoraggio comportamentale a runtime (strumenti come Falco, Tetragon o Cilium eBPF) completa il quadro, segnalando syscall anomale, tentativi di escalation e connessioni inattese. E, come visto nell'introduzione, aggiornare kernel e Docker Engine con continuità è il presupposto di tutto il resto.

Checklist rapida prima del deployment

Controllo Comando/configurazione chiave
Utente non root USER nel Dockerfile, -u, runAsUser
Capabilities minime --cap-drop all --cap-add ...
Niente escalation no-new-privileges / allowPrivilegeEscalation: false
Filesystem read-only --read-only + --tmpfs
Risorse limitate --memory, --cpus, --ulimit, --restart
Rete segmentata reti dedicate / Network Policy
Porte su localhost -p 127.0.0.1:...
Scansione immagini Trivy, Grype, Snyk, Docker Scout in CI/CD
Secret gestiti Docker Secrets, mai in immagine
Profili runtime seccomp/AppArmor/SELinux attivi
Host e daemon aggiornati patch di kernel e Docker Engine
Socket daemon non esposto mai montare /var/run/docker.sock

Il consiglio di Digital Lab

La sicurezza dei container non si risolve con uno strumento solo: è una catena di decisioni che parte dal Dockerfile e arriva al runtime, passando dalla pipeline CI/CD. I dodici errori di questa guida sono il punto di partenza; il modo più efficace per non ripeterli è trasformarli in controlli automatici, che bloccano la build o il deployment quando una condizione non è rispettata.

Le raccomandazioni qui riportate sono verificate alla data di redazione (30 agosto 2026) sull'OWASP Docker Security Cheat Sheet e sulla guida NIST SP 800-190. Le best practice evolvono con le vulnerabilità: rivedi periodicamente questi controlli, aggiorna host e runtime e tieni la pipeline di sicurezza sempre accesa.

Vuoi un percorso strutturato per portare i container e la sicurezza nel tuo team, con laboratori pratici e docenti certificati? Scopri i corsi container e DevSecOps di Digital Lab.

Scopri i corsi DevSecOps

Archivio