Sicurezza
Il punto di partenza
Sezione intitolata “Il punto di partenza”Sirio parla con il socket Docker. Chi può usare il socket Docker può diventare root
sull’host: basta avviare un container privilegiato che monta /. Di conseguenza chi entra in
Sirio controlla la macchina, e ogni scelta di progetto parte da qui.
Cosa fa Sirio
Sezione intitolata “Cosa fa Sirio”Autenticazione
Sezione intitolata “Autenticazione”- Il primo account amministratore è creato dal wizard di primo avvio. L’endpoint di setup si chiude appena esiste un utente: non è possibile “reclamare” un’istanza già configurata. Gli account successivi si creano da Utenti, da parte di un amministratore.
- Password con bcrypt a costo 12, minimo 10 caratteri, massimo 72 byte (oltre, bcrypt troncherebbe silenziosamente).
- Al login inesistente viene comunque calcolato un hash, per non rivelare dai tempi di risposta quali username esistono.
- Sessioni server-side: il cookie contiene un token casuale da 256 bit, nel database ne è salvato solo lo SHA-256. Un dump del database non permette di impersonare nessuno.
- Cookie
HttpOnly,SameSite=Lax,SecurequandoSIRIO_SECURE_COOKIES=trueo con TLS diretto. - Il cambio password invalida tutte le sessioni, compresa quella di un eventuale intruso.
- Rate limiting sul login: 10 tentativi ogni 15 minuti per IP, con
Retry-Afternella risposta.
Ogni richiesta non sicura (POST, PUT, DELETE) deve portare l’header X-Sirio-CSRF con il token
della sessione, che la SPA riceve da /api/status. Un sito terzo può far partire una richiesta
con il cookie, ma non può leggere il token.
I WebSocket sono protetti dal controllo dell’Origin, che rifiuta le connessioni cross-site.
Autorizzazione
Sezione intitolata “Autorizzazione”Ogni rotta sotto /api che non sia status, setup o login passa dal middleware di
autenticazione. Non esiste alcun endpoint Docker o pipeline raggiungibile senza sessione.
L’unica eccezione è /webhooks/pipelines/{id}, che si autentica con la firma HMAC.
Un amministratore può fare tutto, e solo un amministratore gestisce utenti e permessi: non è un permesso assegnabile, altrimenti un utente potrebbe concedersi qualsiasi altro accesso.
Tutti gli altri hanno quello che un amministratore assegna loro, su due livelli:
- Sezioni del pannello —
sites,proxy,packages,docker,settings— ognuna dà accesso a un’intera sezione, su tutti i siti. - Singoli siti: dare accesso a un sito concede di base tutte le azioni su quel sito.
Le azioni sono raggruppate per area (repository, pipeline, domini, container) e, dentro ognuna,
per singola operazione: creare, modificare, cambiare sito, eliminare, avviare una pipeline.
Ciascuna si può togliere per conto suo — sul singolo sito, dalla riga del sito, oppure
globalmente, e in quel caso viene tolta su tutti i siti raggiunti dal permesso sites e sui
container che non appartengono a nessun sito. Togliere un’intera area toglie anche le sue
operazioni. Quello che non si toglie in questo modo è la lettura: chi vede un sito vede cosa c’è
dentro.
Il server decide ogni richiesta su questa base, comprese quelle che l’interfaccia non propone mai: nascondere un pulsante è una comodità, non il controllo.
Webhook
Sezione intitolata “Webhook”La firma viene verificata prima di leggere il payload e prima di qualunque esecuzione:
- GitHub e Gitea:
X-Hub-Signature-256(HMAC-SHA256), confrontata a tempo costante; - GitLab:
X-Gitlab-Token, confrontato a tempo costante; X-Hub-Signature(SHA-1) accettata solo per compatibilità con installazioni vecchie.
Il secret è generato dal server (32 byte casuali), mostrato una sola volta e conservato cifrato. Il corpo è limitato a 1 MiB e c’è un rate limit di 60 chiamate al minuto per IP.
Anche con firma valida, la pipeline parte solo se il ref corrisponde al trigger configurato: un push su un branch diverso viene registrato e ignorato.
Segreti
Sezione intitolata “Segreti”Token Git, chiavi SSH di deploy e secret dei webhook sono cifrati con AES-256-GCM. La chiave
sta in secret.key (permessi 0600) o nella variabile SIRIO_SECRET_KEY, mai nel database.
L’API non restituisce mai un segreto: espone solo un flag has_secret. I segreti non compaiono
nei log.
Esecuzione delle pipeline
Sezione intitolata “Esecuzione delle pipeline”- I comandi provengono dalla configurazione scritta dall’amministratore, non dal payload dei webhook. I dati non fidati (ref, commit) arrivano agli step solo come variabili d’ambiente: non vengono mai concatenati dentro una stringa di comando.
- Gli step non-shell (build, compose, restart) sono eseguiti passando gli argomenti come array, senza shell di mezzo. I sottocomandi compose sono su whitelist; gli argomenti aggiuntivi di uno step compose sono divisi sugli spazi e vengono dopo il sottocomando, quindi non possono sostituirlo.
workdir,contextecompose_filedevono essere relativi al checkout: percorsi assoluti o con..vengono rifiutati alla validazione.- Gli URL dei repository sono limitati a
https://,ssh://e alla formagit@host:path. Schemi comeext::permetterebbero l’esecuzione di comandi arbitrari tramite git. - I processi figli non ereditano l’ambiente del servizio: ricevono solo
PATH,LANGe le variabili della pipeline. UnEnvironment=con segreti nell’unit systemd non trapela negli step. - Il token Git non passa mai dalla riga di comando (sarebbe visibile in
ps) né finisce nel.git/configdel checkout: viene fornito a git tramiteGIT_ASKPASS. - Ogni step ha un timeout (30 minuti di default) e alla cancellazione viene terminato l’intero process group, non solo il processo padre.
Domini e reverse proxy
Sezione intitolata “Domini e reverse proxy”- Il Caddyfile è generato concatenando valori scritti dall’amministratore. Un FQDN che
contenga un a capo o una graffa inietterebbe direttive arbitrarie nella configurazione del
proxy. Per questo ogni campo che finisce nel file — dominio, path, destinazione, porta,
indirizzo ACME — passa da una validazione per whitelist in
internal/proxy/validate.goprima della generazione. La generazione non fa escaping, perché in un Caddyfile non esiste una forma di quoting che renda sicuro un input arbitrario: la difesa è a monte. caddy validategira su ogni configurazione prima di attivarla, come seconda linea. Se fallisce, la configurazione precedente resta in vigore.- I comandi verso il container del proxy sono passati come array di argomenti, senza shell.
- Una rotta di tipo
hostpermette di raggiungere qualsiasi indirizzo visibile dal proxy, inclusi servizi interni. È accettabile — chi amministra Sirio ha già accesso al socket Docker, quindi root sull’host — ma ogni creazione e modifica di rotta finisce nel registro attività con la destinazione. - Il proxy gira come container, non come servizio dell’host: Sirio scrive la configurazione solo
dentro
SIRIO_DATA_DIRe non richiede di allargareReadWritePathsnell’unit systemd né privilegi di reload su servizi di sistema. - Con
SIRIO_PANEL_DOMAINil proxy raggiunge il pannello tramite un socket Unix inSIRIO_DATA_DIR/proxy(0700, montata solo nel container del proxy), non una porta TCP. Solo su quel listener Sirio prende l’indirizzo del client daX-Forwarded-For, perché lì l’header può essere solo di Caddy: Caddy scarta quello inviato dal client e imposta il peer che vede. Ovunque altrove l’header resta ignorato, quindi non serve ad aggirare il rate limit dei login. Il dominio del pannello passa dalla stessa validazione di quello di un sito, e non può essere un wildcard. - La verifica DNS di un dominio è un avviso e non un blocco, ed è deliberato: l’IP pubblico della macchina non è determinabile in modo affidabile dall’interno, e un confronto inaffidabile userebbe la sicurezza come pretesto per bloccare configurazioni legittime.
Pacchetti di sistema
Sezione intitolata “Pacchetti di sistema”Applicare aggiornamenti richiede root, che Sirio non ha e non prende. Il servizio deposita una
richiesta in SIRIO_DATA_DIR/packages, una unit systemd dedicata la raccoglie e la esegue: né
sudo (bloccato da NoNewPrivileges) né un allentamento di ProtectSystem=strict, che renderebbe
scrivibile mezzo filesystem per l’intero servizio invece che per una singola operazione.
L’insieme dei comandi eseguibili è chiuso e verificato due volte, in Sirio e nell’helper di root,
perché chi scrive la richiesta è meno fidato di chi la esegue. I nomi dei pacchetti passano una
convalida sulla forma, sono accettati solo se già presenti fra gli aggiornabili e arrivano ad apt
come lista di argomenti, mai concatenati in una stringa di shell. Fuori dall’insieme restano
dist-upgrade, l’installazione e la rimozione di pacchetti arbitrari. Dettagli in
pacchetti.md.
Le caselle degli helper
Sezione intitolata “Le caselle degli helper”Ogni helper privilegiato (pacchetti, installazione di Docker, log dei container, fail2ban,
aggiornamenti, alimentazione) parla con Sirio attraverso file in una cartella sotto SIRIO_DATA_DIR. Quella
cartella, e SIRIO_DATA_DIR stessa, appartengono all’utente del servizio, che può sostituire con
un symlink qualunque file o cartella lì dentro. Per questo gli helper non toccano mai quei file
come root: leggere e rimuovere la richiesta, scrivere il log e l’esito avvengono come utente del
servizio (setpriv, o runuser se manca). Un symlink porta così solo dove quell’utente poteva già
scrivere. install.sh crea quelle cartelle nello stesso modo. Root scrive solo nei posti suoi
(/etc, /usr/local, una /tmp privata): per esempio sirio-fail2ban-ctl tiene la copia del suo
file in jail.d, da rimettere se fail2ban rifiuta quello nuovo, nella /tmp privata della sua
unit, mai nella casella.
Aggiornamenti di Sirio
Sezione intitolata “Aggiornamenti di Sirio”Un aggiornamento sostituisce il binario di cui si fidano gli helper di root, quindi è un’azione riservata agli amministratori, e una release diventa installabile per la sua firma ed25519, verificata da Sirio e di nuovo come root con le chiavi del binario installato, non per il server da cui arriva. Dettagli in aggiornamenti.md.
Riavvio e spegnimento del server
Sezione intitolata “Riavvio e spegnimento del server”Gli amministratori possono riavviare o spegnere la macchina dal menù utente; come gli
aggiornamenti, non è un permesso assegnabile, perché porta giù tutti i siti e una VPS spenta torna
solo dalla console del provider. Sirio deposita in SIRIO_DATA_DIR/power una richiesta che
contiene solo reboot o poweroff e un token per l’esito; l’unit sirio-power (root,
ProtectSystem=strict, che scrive solo nella sua casella) sceglie il verbo di systemctl dalla
propria lista chiusa e lo programma cinque secondi dopo con un timer transitorio di systemd, così
la risposta arriva prima al pannello. Una seconda richiesta mentre una è in attesa viene
rifiutata. Le esecuzioni di pipeline e di backup in corso andrebbero perse, quindi il pannello
avvisa e chiede conferma; un’operazione privilegiata in corso (pacchetti, installazione di Docker,
configurazione di fail2ban, un aggiornamento di Sirio) non si può scavalcare affatto, perché
interromperla a metà può lasciare il sistema danneggiato. Entrambe le azioni finiscono nel
registro attività (host.reboot, host.poweroff), con l’indicazione delle esecuzioni interrotte.
Eliminazione dei log dei container
Sezione intitolata “Eliminazione dei log dei container”Docker non ha un’API per eliminare i log di un container, e i file sono di root, sotto la data root
di Docker. Stesso schema dei pacchetti: Sirio deposita in SIRIO_DATA_DIR/container-logs una
richiesta che nomina solo l’ID completo di un container, e l’unit sirio-logs (root) la riconvalida,
chiede a Docker stesso quali file appartengono a quel container e li svuota — mai un percorso preso
dalla richiesta, mai un link simbolico, solo i driver json-file e local. Un container in
esecuzione viene prima fermato e poi riavviato, e il pannello lo dice prima di chiedere conferma:
dockerd tiene un proprio offset di scrittura nel file attivo, e svuotarlo sotto un container in
esecuzione lascia docker logs -f a leggere oltre la fine reale fino alla rotazione successiva.
L’helper rifiuta un container in esecuzione anche se glielo si chiede. Serve il permesso
containers.edit, e l’operazione finisce nel registro attività con lo spazio liberato.
Porte in ascolto
Sezione intitolata “Porte in ascolto”La pagina Porte (Host → Porte, permesso settings) elenca tutte le porte TCP e UDP in ascolto
sull’host e segnala quelle rischiose: SSH sulla porta predefinita 22 o che accetta password o il
login di root (o che chiede ancora la password tramite il keyboard-interactive di PAM dopo
PasswordAuthentication no) o password vuote, nessun fail2ban a sorvegliare un sshd pubblico,
database e cache su un’interfaccia pubblica, protocolli in chiaro (Telnet, FTP,
rsh), l’API Docker, la condivisione file, il desktop remoto, i pannelli di amministrazione e
Sirio stesso servito in HTTP in chiaro su tutte le interfacce. Le regole e il catalogo delle
porte note stanno in internal/ports.
Funziona senza privilegi, e questo delimita ciò che può dire:
- I socket arrivano da
/proc/net/{tcp,udp}[6], leggibili da qualunque utente. Sirio giudica una porta dall’indirizzo a cui è legata —0.0.0.0,::o un indirizzo pubblico è pubblica, un indirizzo privato o di VPN è rete privata, localhost è solo locale — ma non può leggere il firewall (servirebbeCAP_NET_ADMIN): una porta pubblica può comunque essere filtrata da ufw, nftables o dal provider. Né può sapere quale processo possiede il socket di un altro utente; mostra invece il nome dell’utente proprietario. - Le porte pubblicate dai container arrivano da Docker e sono segnalate a parte, perché Docker
scrive regole iptables proprie che scavalcano ufw e firewalld: il caso classico del
database “chiuso” dal firewall e aperto al mondo. Pubblicale come
127.0.0.1:PORTAquando servono solo all’host; ai siti non serve nessuna porta pubblicata, perché il proxy raggiunge i container sulla sua rete. Per questo il form Nuovo container pubblica su127.0.0.1a meno che tu non scelga tutte le interfacce (o scriva un indirizzo nella riga), e avvisa quando una porta finirebbe pubblica. - I controlli su SSH leggono
sshd_configcome fa sshd (Include sul posto, vince il primo valore, blocchi Match esclusi). I drop-in che Sirio non può leggere — alcune distro li installano0600— rendono sconosciuti i valori interessati invece di presumerli. - Spostare SSH dalla porta 22 è segnalato come avviso, non come soluzione: riduce le scansioni automatiche e il rumore nei log, ma a proteggere davvero il server sono l’accesso solo con chiave, niente login di root e fail2ban o un elenco di IP ammessi.
fail2ban
Sezione intitolata “fail2ban”Con sshd raggiungibile dall’esterno, la pagina Porte controlla anche che fail2ban sia
installato, attivo e con la jail sshd accesa — un avviso dove SSH accetta ancora password, una
nota dove è solo a chiavi, perché lì fail2ban riduce soprattutto il rumore nei log. Se la jail è
accesa lo legge dalla configurazione, combinata come fa fail2ban (jail.conf, jail.d/*.conf,
jail.local, jail.d/*.local, vince l’ultimo valore); lo stato effettivo richiederebbe il socket,
che è solo di root.
Dalla stessa pagina, con i permessi settings e packages, Sirio può configurarlo: stesso schema
dei pacchetti, una richiesta in SIRIO_DATA_DIR/fail2ban raccolta dalla unit sirio-fail2ban
(root). La richiesta non porta altro che l’intenzione — l’helper riconosce apt, dnf o yum,
abilita EPEL su Rocky/Alma/CentOS, legge le porte SSH da sshd -T, legge il log di sshd dal
journal quando c’è il modulo systemd di Python, scrive /etc/fail2ban/jail.d/sirio-sshd.conf
(che il tuo jail.local continua a sovrascrivere), riavvia fail2ban e verifica che la jail sia
davvero su. Blocca nella catena INPUT, quindi protegge i servizi dell’host come SSH, non le
porte pubblicate dai container. Non disponibile senza systemd (Alpine).
La pagina fail2ban, con il permesso settings, mostra il server in esecuzione: ogni jail, i suoi
contatori e gli indirizzi che banna, con la scadenza di ciascun ban. Quello stato sta solo nel
socket di fail2ban, che è di root, quindi passa da una seconda unit, sirio-fail2ban-ctl (root),
con una casella tutta sua in SIRIO_DATA_DIR/fail2ban/ctl — un’installazione tiene occupata
sirio-fail2ban per minuti, e una lettura non può aspettarla. La richiesta indica un’azione da un
insieme chiuso e un token casuale per il nome del file di risposta, nient’altro; l’helper
interroga fail2ban con la sua stessa libreria client in un solo processo e risponde in JSON. La sua
unit gira con ProtectSystem=strict e può scrivere solo in quella casella. Sirio riusa una
lettura per qualche secondo prima di chiedere di nuovo, così una pagina che si aggiorna da più
schede non avvia un processo root ogni volta.
Dalla stessa pagina si può bannare un indirizzo in una jail o sbloccarlo, sempre con il solo
settings, e ogni modifica andata a buon fine finisce nel registro di audit (fail2ban.ban,
fail2ban.unban). La jail e l’indirizzo vengono controllati due volte, in Go e di nuovo
nell’helper, e arrivano a fail2ban come argomenti del suo protocollo, mai attraverso una shell. Un
ban chiesto a mano fail2ban lo applica qualunque cosa dica la sua configurazione — banna senza
obiezioni un indirizzo presente in ignoreip — quindi Sirio rifiuta quelli che riconosce come
errori: indirizzi di loopback, non specificati e multicast, tutto ciò che ignoreip della jail
copre (i nomi host lì dentro non vengono risolti) e l’indirizzo da cui arriva la richiesta.
Quest’ultimo controllo vede l’indirizzo che vede Sirio: dietro al proxy gestito è quello vero del
client, ma dietro a un tuo reverse proxy è quello del proxy, e il controllo non serve.
La stessa pagina imposta i limiti della jail sshd (fallimenti prima del ban, la finestra in cui
vengono contati, la durata del ban) e una whitelist di indirizzi e reti che nessuna jail banna mai.
Entrambi stanno in un unico file di Sirio, /etc/fail2ban/jail.d/sirio-tuning.conf —
[DEFAULT] ignoreip e [sshd] — che scrive solo sirio-fail2ban-ctl, per cui la sua unit può
scrivere in quella directory oltre che nella sua casella. La richiesta porta l’intero file sotto
forma di valori (interi, indirizzi e reti CIDR, controllati in Go e di nuovo nell’helper): l’helper
non tiene stato. Scrive il file, esegue fail2ban-client -t sull’intera configurazione e poi
ricarica fail2ban, che mantiene i suoi ban; se uno dei due passi fallisce rimette il file
precedente, così una modifica fatta dal pannello non lascia mai fail2ban impossibilitato a partire.
Essendo un .conf, il file perde contro jail.local e jail.d/*.local: la pagina legge la
configurazione come la combina fail2ban e dice quale dei tuoi file sovrascrive un valore impostato
da Sirio. Il loopback è sempre nella whitelist, le reti più ampie di /8 (IPv4) o /16 (IPv6) vengono
rifiutate e i nomi host non sono accettati.
Lo stesso file può attivare la jail recidive, che legge il log di fail2ban stesso e banna, su
tutte le porte, gli indirizzi che le altre jail continuano a bannare (con i valori predefiniti di
fail2ban, cinque ban in un giorno valgono una settimana). La richiesta dice solo “attiva”: l’helper
legge logtarget dalla configurazione di fail2ban e scrive da sé il backend — auto con quel file
come logpath, oppure systemd per SYSTEMD-JOURNAL — e rifiuta tutto il resto, perché alcune
distribuzioni impostano backend = systemd per ogni jail e una recidive che guarda il journal
mentre fail2ban scrive su un file non bannerebbe mai nessuno. Dato che blocca tutte le porte,
pannello compreso, la pagina chiede di tenere i tuoi indirizzi nella whitelist. Una recidive
attivata da un tuo file viene mostrata come tale, e lasciata stare.
I ban recenti vengono dal database dei ban di fail2ban, che sirio-fail2ban-ctl apre in sola
lettura (la sua unit lì non può comunque scrivere), trovato attraverso la configurazione così
funziona anche con fail2ban fermo. Ogni ban mostra le ultime righe di log che lo hanno causato;
sono ciò che un client ha inviato, quindi la pagina le mostra come testo semplice. È una memoria,
non un registro: fail2ban dimentica un ban dbpurgeage dopo la sua fine (un giorno di default), e
un indirizzo sbloccato a mano subito. La pagina lo legge solo quando richiesto.
Server SFTP
Sezione intitolata “Server SFTP”Opzionali (SIRIO_SFTP_ENABLED, spenti di default). Dettagli in sftp.md.
- Docker monta qualsiasi cosa gli venga chiesta con i diritti di root, quindi ciò che il server di un sito può esporre lo decide Sirio prima che il container esista, da ciò che i container del sito montano in quel momento, e lo decide di nuovo a ogni modifica e ogni minuto. Le directory di sistema, il socket e la directory dati di Docker, la directory dati di Sirio, le home degli utenti e i file nascosti al loro interno non vengono mai esposti, né le directory che ne contengono una; e neppure i dati di un database, i mount condivisi con un altro sito (o con nessun sito) e i percorsi che Sirio non riesce a risolvere. I percorsi vengono controllati così come sono scritti e dopo averne seguito i symlink, e il container monta quello risolto.
- Chi può creare container su un sito può già montarci qualsiasi percorso dell’host: è root sull’host, come ovunque ci sia di mezzo Docker. I controlli dell’SFTP impediscono che quel potere arrivi agli account SFTP del sito, che non sono utenti di Sirio.
- Il server è il binario di Sirio, da solo in un’immagine che Sirio costruisce a partire da esso:
nessuna immagine di terzi di cui fidarsi. Serve solo il sottosistema SFTP, apre ogni mount come
os.Root, rifiuta symlink, hard link e rinomine tra mount diversi, e non permette mai a un client di cambiare il proprietario o i bit speciali dei permessi. - Il suo container rinuncia a ogni capability tranne
CHOWN,DAC_OVERRIDEeFOWNER, gira conno-new-privileges, il filesystem radice in sola lettura, limiti su processi e memoria, su una rete senza traffico tra container, e monta la sua configurazione in sola lettura. - Le password sono salvate come hash bcrypt, le chiavi host sigillate con la secret box. Il file di configurazione letto dal server contiene solo hash e chiavi pubbliche, e Sirio lo valida con le stesse regole del server prima di scriverlo.
- I limiti per IP su password sbagliate e connessioni presuppongono che l’indirizzo del client arrivi al container: dietro il proxy userland di Docker tutti i client condividono quello del gateway.
Trasporto e intestazioni
Sezione intitolata “Trasporto e intestazioni”X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer e una
CSP che consente solo risorse dell’origine — la SPA è interamente servita dal binario, non
carica nulla da CDN.
Cosa devi fare tu
Sezione intitolata “Cosa devi fare tu”- Metti HTTPS davanti. Senza TLS il cookie di sessione è leggibile in rete. Poi attiva
SIRIO_SECURE_COOKIES=true. - Richiudi la porta di Sirio quando hai HTTPS. Il default
SIRIO_LISTEN=0.0.0.0:22722serve a raggiungere il pannello suhttp://IP:22722prima di avere un dominio: è in chiaro, quindi è una condizione di partenza, non di esercizio. Con un reverse proxy sull’host, torna a127.0.0.1:22722e raggiungi il pannello solo attraverso di lui. Con il proxy gestito da Sirio usaSIRIO_PANEL_DOMAINe spostaSIRIO_LISTENsu un’altra porta di loopback: una rotta host versohost.docker.internalsmette di funzionare se Sirio ascolta su127.0.0.1(vedi domini.md). - Restringi l’accesso. Se puoi, tieni il pannello dietro VPN o limitalo per IP nel proxy. È amministrazione di sistema, non un sito pubblico.
- Custodisci
secret.key. Con il database e la chiave si ricavano tutti i token di deploy. Backup separati. - Usa credenziali Git minime. Deploy key in sola lettura, token con lo scope più stretto possibile.
- Leggi il registro attività. In Impostazioni: login falliti, webhook rifiutati, azioni sui container.
Limiti noti
Sezione intitolata “Limiti noti”- Un solo ruolo: chi accede può fare tutto. RBAC granulare è rimandato.
- L’helper dei pacchetti gira come root: restringe cosa può essere eseguito, non chi può chiederlo. Chi entra nel pannello può aggiornare la macchina.
- Eliminare i log di un container li distrugge per tutti,
docker logscompreso: chi deve conservarli li mandi altrove (un log driver, un collector) prima di affidarsi a questo pannello. - Nessun secondo fattore.
- Dietro reverse proxy il rate limiting vede l’IP del proxy, non quello del client.
- Uno step shell è, per sua natura, esecuzione di codice arbitrario sull’host: chi può modificare una pipeline può fare qualsiasi cosa. Non è una falla, è la funzione del prodotto.
Segnalare una vulnerabilità
Sezione intitolata “Segnalare una vulnerabilità”Aprire una issue pubblica per una vulnerabilità la rende sfruttabile prima che ci sia una correzione. Scrivi in privato al manutentore descrivendo il problema e come riprodurlo.