NextPDF Gotenberg: sicurezza e operatività
In sintesi
Sezione intitolata “In sintesi”Questo bridge trasmette sulla rete a un servizio esterno i documenti gestiti dall’applicazione. Di conseguenza, diventa sia una superficie di richiesta lato server sia una superficie di sicurezza del trasporto. Il pacchetto implementa controlli specifici e verificabili su entrambe. Da solo, tuttavia, non mette in sicurezza l’intero sistema. I controlli sono efficaci solo insieme al modo in cui il servizio Gotenberg viene distribuito e gestito. Questa pagina descrive i controlli implementati e gli obblighi operativi necessari a completarli.
Nessun controllo qui descritto va inteso come una garanzia. Ognuno corrisponde a un comportamento definito, coperto da test e con limiti dichiarati.
I due livelli di policy
Sezione intitolata “I due livelli di policy”Il bridge adotta due policy di sicurezza distinte, che operano a livelli diversi:
- Policy di trasporto (
GotenbergSecurityPolicy) — applicazione dello schema URL, controllo della server-side request forgery (SSRF), difesa dal DNS rebinding, limiti sulla dimensione dell’input e controllo dei nomi dei file. Questo è il livello descritto nel dettaglio di seguito. - Policy di parsing HTML — una policy di contenuto a livello di parsing, il cui valore predefinito è la policy predefinita del core NextPDF, applicata prima che il contenuto possa raggiungere un renderer. È complementare e indipendente rispetto alla policy di trasporto. Questa pagina riguarda la policy di trasporto.
Controllo della server-side request forgery (SSRF)
Sezione intitolata “Controllo della server-side request forgery (SSRF)”L’URL dell’API configurato viene controllato prima che qualunque byte lasci il processo. Il controllo si articola in tre parti.
Applicazione dello schema. È consentito solo https (senza distinzione tra maiuscole e minuscole). Un URL http:// viene rifiutato. Transport Layer Security è quindi obbligatorio per ogni conversione e per il probe di integrità.
Controllo degli indirizzi. Se l’host è un IP letterale, viene rifiutato quando rientra in un intervallo privato o riservato. Se l’host è un nome, viene risolto in tutti i suoi record A e AAAA e la richiesta viene rifiutata se uno qualsiasi degli indirizzi risolti è privato o riservato. Risolvere l’intero set di record, invece di un solo indirizzo, è il controllo che impedisce a un aggressore di nascondere un indirizzo privato dietro un nome che restituisce anche un indirizzo pubblico. Questo corrisponde all’approccio che le linee guida OWASP per la prevenzione dell’SSRF descrivono come il recupero di ogni indirizzo IP dietro il nome di dominio (record A e AAAA, per IPv4 e IPv6) e la convalida di ciascuno rispetto a un elenco di indirizzi consentiti (OWASP Cheat Sheet Series, prevenzione SSRF, difesa a livello applicativo; ancorato nel sidecar RAG della pagina).
Riverifica time-of-check/time-of-use (TOCTOU). Il set di indirizzi acquisito durante la convalida viene risolto nuovamente e confrontato subito prima della richiesta. Se compare un nuovo indirizzo, la richiesta viene interrotta con un errore di DNS rebinding. Questo chiude la finestra tra il controllo di convalida e la connessione che un attacco di rebinding potrebbe altrimenti sfruttare.
Quando il bridge utilizza il proprio trasporto cURL con pinning, il set di indirizzi convalidato è vincolato alla connessione tramite CURLOPT_RESOLVE, in modo che il kernel si connetta all’indirizzo verificato anziché a qualunque indirizzo restituito da una nuova risoluzione DNS al momento della connessione. Il follow dei redirect è disabilitato su quel trasporto (CURLOPT_FOLLOWLOCATION disattivato, CURLOPT_MAXREDIRS a zero), quindi un 3xx non può reindirizzare silenziosamente la richiesta verso un host non verificato. La risposta affiora invece al livello della policy.
Conseguenza operativa. Per progettazione, la protezione SSRF rifiuta gli indirizzi privati e riservati. Se Gotenberg viene eseguito su una rete privata, non è possibile puntare il bridge al suo indirizzo privato. Occorre esporlo tramite un indirizzo accettato dalla protezione e proteggere quel percorso con segmentazione di rete e autenticazione, come descritto più avanti nella sezione sulla distribuzione.
Sicurezza del trasporto e pinning della chiave pubblica
Sezione intitolata “Sicurezza del trasporto e pinning della chiave pubblica”La verifica TLS del peer e dell’host è sempre attiva nel trasporto cURL con pinning (CURLOPT_SSL_VERIFYPEER true, CURLOPT_SSL_VERIFYHOST 2). Oltre alla convalida standard della catena, il bridge supporta il pinning del SubjectPublicKeyInfo (SPKI).
Ogni pin è un hash SHA-256 del SubjectPublicKeyInfo del server, espresso come sha256/<base64>. Il bridge accetta un certificato il cui hash SPKI corrisponde a un pin qualsiasi del set combinato di pin primari e di backup. Questo modello con pin di backup segue RFC 7469 §4.3, che individua nel pin di backup — l’impronta di una coppia di chiavi secondaria non ancora distribuita — il modo principale per ripristinare il servizio dopo un errore involontario di convalida del pin, e §2.5, che richiede che il set di pin includa almeno un pin non presente nella catena di certificati corrente (RFC 7469 §4.3 e §2.5; ancorato nel sidecar RAG della pagina). Il codice del bridge dichiara RFC 7469 §2.1 e §2.6 per la semantica della presenza di almeno un pin di backup e dell’intersezione del set combinato. Il pinning è facoltativo: senza pin configurati si applica la convalida standard della catena e il pinning non viene applicato.
Un pin che non può essere analizzato correttamente solleva un errore di configurazione prima di qualsiasi richiesta. Un certificato attivo il cui SPKI non corrisponde ad alcun pin configurato fa fallire la richiesta a livello di trasporto — per progettazione.
Procedura di rotazione dei pin
Sezione intitolata “Procedura di rotazione dei pin”Una rotazione eseguita male blocca l’accesso del bridge al servizio. Per ruotare senza interruzioni di servizio:
- Prima di cambiare la chiave del server, generare il pin SPKI per la nuova chiave e aggiungerlo all’elenco dei pin di backup. Distribuire quella configurazione. Il bridge accetta ora sia la chiave corrente sia quella futura.
- Sostituire il certificato o la chiave del server con la nuova chiave.
- Verificare che le conversioni continuino a riuscire (la nuova chiave ora corrisponde al pin di backup).
- Spostare il nuovo pin dall’elenco di backup all’elenco primario e rimuovere il pin della chiave dismessa. Distribuire.
- Generare e predisporre il pin per la rotazione successiva come nuovo backup, in modo che il set disponga sempre di una riserva utilizzabile.
Mantenere l’elenco di backup separato da quello primario consente di predisporre e convalidare il pin successivo senza toccare quello attivo.
Autenticazione
Sezione intitolata “Autenticazione”Quando apiKey non è vuoto, viene inviato come header Authorization: Bearer sulla richiesta di conversione. Il campo è contrassegnato con #[\SensitiveParameter], in modo che il valore venga oscurato dagli stack trace. Il bridge non recupera il segreto per conto dell’utente; fornirlo da un gestore di segreti all’avvio del processo e non sottoporlo mai a commit. Il token non viene scritto nel log delle richieste — la voce di debug registrata contiene solo l’URL, il nome del file, il formato e la lunghezza del contenuto.
Confine di fiducia della risposta
Sezione intitolata “Confine di fiducia della risposta”Una risposta viene accettata solo se lo stato è 200, il Content-Type contiene application/pdf e il corpo inizia con la firma %PDF. Il controllo della firma sui byte è necessario perché un tipo di contenuto dichiarato, da solo, non stabilisce cosa siano i byte — lo stesso ragionamento che lo standard WHATWG MIME Sniffing formalizza nel suo algoritmo di sniffing del tipo MIME, che deriva un tipo calcolato dal confronto dei pattern dei byte iniziali anziché dal tipo fornito. Le linee guida OWASP sul caricamento dei file enunciano il principio applicativo corrispondente: convalidare il tipo di file e non fidarsi dell’header Content-Type dichiarato, perché può essere falsificato (WHATWG MIME Sniffing §6.2.3; OWASP Cheat Sheet Series, convalida del caricamento di file; entrambi ancorati nel sidecar RAG della pagina). Il bridge applica un controllo equivalente in modo difensivo sul lato in entrata: una mancata corrispondenza solleva un’eccezione tipizzata e i byte non vengono mai restituiti come risultato.
Questo confine spiega anche perché il contratto PSR-18 è rilevante qui. Un client PSR-18 solleva un’eccezione solo quando non può inviare la richiesta o non può analizzare la risposta in un oggetto PSR-7 — non solleva eccezioni per un codice di stato di errore. Una risposta 4xx/5xx ben formata viene restituita normalmente al chiamante (PSR-18, «Exceptions»; ancorato nel sidecar RAG della pagina). Il bridge esamina quindi autonomamente lo stato, il tipo e la firma, anziché presumere che una risposta restituita sia andata a buon fine. La semantica HTTP di una violazione del vincolo sul content-type — un rifiuto 415 (Unsupported Media Type), in cui un server rifiuta contenuto in un formato non supportato — è il modello a cui si ispira il controllo in entrata (RFC 9110 §15.5.16; ancorato nel sidecar RAG della pagina).
Limiti delle risorse
Sezione intitolata “Limiti delle risorse”L’unico limite di risorse interno al processo è maxFileSize (predefinito 52.428.800 byte = 50 MiB), applicato prima della richiesta, così un input di dimensioni eccessive non raggiunge mai il servizio. Nel bridge non esiste alcun limite integrato di concorrenza, di frequenza o sulla dimensione dell’output. Questi aspetti sono responsabilità della distribuzione e del chiamante (vedere /integrations/gotenberg/production-usage/). Impostare maxFileSize al valore più piccolo richiesto dai propri documenti reali — un limite più stringente è un controllo anti-denial-of-service più economico.
Distribuire e mettere in sicurezza il servizio Gotenberg
Sezione intitolata “Distribuire e mettere in sicurezza il servizio Gotenberg”Il bridge è sicuro solo nella misura in cui lo è il servizio che chiama. La gestione del servizio spetta all’utente; gli obblighi seguenti completano i controlli descritti sopra.
- Terminare il TLS davanti a Gotenberg. Il container di Gotenberg utilizza per impostazione predefinita HTTP in chiaro. Il bridge richiede HTTPS, quindi collocare Gotenberg dietro un reverse proxy, un ingress o un service mesh che termina il TLS e puntare il bridge all’endpoint HTTPS. Eseguire il pinning dell’SPKI del proxy se si abilita il pinning.
- Non esporre Gotenberg pubblicamente. Esegue la conversione dei documenti con motori della classe LibreOffice e Chromium e non è un servizio rivolto a Internet. Limitare l’ingress agli host applicativi che lo chiamano, tramite policy di rete o firewall.
- Richiedere l’autenticazione sul percorso. Il bridge invia un bearer token quando è configurato; applicarlo (o applicare il TLS reciproco) sul proxy in modo che una richiesta non autenticata non possa raggiungere il motore di conversione.
- Fissare una versione specifica del servizio. Il bridge presuppone esattamente due percorsi di servizio —
/forms/libreoffice/converte/health. Fissare l’immagine Gotenberg a uno specifico tag di patch, verificare quei due percorsi rispetto alla versione che si distribuisce e riverificare a ogni aggiornamento. - Dimensionare la capacità di conversione in modo deliberato. Ogni conversione occupa un worker per la durata della richiesta. Dimensionare la distribuzione Gotenberg per il picco di conversioni concorrenti e limitare di conseguenza le conversioni in corso sul lato chiamante. La capacità è una proprietà della propria distribuzione, non di questo pacchetto.
- Trattare gli input di conversione come non attendibili. I documenti inviati per la conversione vengono elaborati da motori complessi. Vincolare
maxFileSize, isolare la distribuzione Gotenberg (segmento di rete dedicato, egress minimo, nessun accesso ai servizi interni) e mantenere il motore aggiornato con le patch.
Ciò che questo pacchetto non dichiara
Sezione intitolata “Ciò che questo pacchetto non dichiara”- Non è «sicuro per impostazione predefinita»: i controlli sono reali ma dipendono da una distribuzione e da una configurazione corrette.
- Non rende la conversione «a prova di manomissione» né l’output «certificato». Convalida il trasporto e la forma della risposta; non attesta il contenuto del documento.
- Non fornisce firma, marca temporale né convalida a lungo termine. Questi sono aspetti di post-elaborazione. Il supporto PAdES dell’edizione Pro è limitato alla baseline B-B e non include B-T, B-LT o B-LTA; nulla in questo bridge implica capacità di marca temporale o LTV.
- Non supporta «tutti i file Office». Supporta i sei formati enumerati e rifiuta tutto il resto prima di qualsiasi richiesta.
Vedere anche
Sezione intitolata “Vedere anche”- /integrations/gotenberg/configuration/ — le regole di selezione del trasporto e il modello di pin completo.
- /integrations/gotenberg/production-usage/ — retry, timeout, concorrenza, osservabilità.
- /integrations/gotenberg/troubleshooting/ — ogni eccezione di sicurezza e il relativo trigger.
- /integrations/gotenberg/overview/ — il flusso di conversione e il modello di dipendenze.