Salta ai contenuti

Sicurezza e gestione operativa di compat-legacy

L’adattatore eredita il modello di sicurezza del motore NextPDF e introduce un insieme limitato e deliberato di irrobustimenti rispetto a TCPDF legacy 6.2.13. Questa pagina indica con precisione ciò che è disponibile e ciò che non lo è, senza enfasi improprie. Leggere con attenzione la sezione sulla firma: il suo ambito è volutamente ristretto.

Tre comportamenti storici di TCPDF 6.2.13 sono stati modificati per ragioni di sicurezza e non sono riconfigurabili nella forma non sicura:

AspettoTCPDF legacy 6.2.13Adattatore
Gestione degli erroriError() chiama die() e termina il processoError() solleva RuntimeException. Osservabile, intercettabile, senza terminare silenziosamente il processo.
Esecuzione di HTMLUn percorso di escape poteva eseguire PHP a partire dal markupLa costante K_TCPDF_CALLS_IN_HTML è fissata a false; il markup non può attivare l’esecuzione di PHP.
Output direttoOutput() scrive direttamente sul buffer di output attivoL’output viene instradato attraverso un bridge di destinazione sicuro. Non inquina un buffer di output controllato dal chiamante.

La modifica alla gestione degli errori segue il principio secondo cui un chiamante deve poter osservare un guasto anziché vedere il processo interrompersi senza controllo. OWASP ASVS 5.0 §16.5.3 stabilisce che un’applicazione dovrebbe fallire in modo controllato e sicuro e prevenire condizioni di fail-open. Sollevare un’eccezione invece di terminare il processo applica tale principio. L’irrobustimento dell’HTML rimuove un punto di esecuzione di codice. Considerare qualsiasi codice legacy che dipendeva dal vecchio comportamento come un difetto da correggere durante /integrations/tcpdf-compat/migration/. Il digest delle clausole fissate si trova nel front-matter della pagina, sotto citations.

L’adattatore espone il metodo SetProtection() di TCPDF e delega al gestore di sicurezza standard del motore NextPDF.

  • Il gestore standard utilizza AES-256. Il parametro legacy $mode è accettato per compatibilità con la firma del metodo e viene ignorato: non esiste alcun modo di selezionare una cifratura più debole tramite questo metodo. Con la modalità strict attiva, un valore non predefinito di $mode solleva un’eccezione, in modo che la migrazione debba tenerne conto esplicitamente (verificato in tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php).
  • Se non viene fornita alcuna password del proprietario, l’adattatore genera una password del proprietario casuale e crittograficamente robusta anziché riutilizzare la password dell’utente. Questo impedisce a chi possiede l’accesso a livello utente di ottenere il controllo del documento a livello di proprietario.
  • La cifratura basata su certificati (a chiave pubblica) non viene eseguita tramite SetProtection(); il suo parametro $pubkeys viene ignorato. Usare il moderno punto di ingresso per la cifratura a chiave pubblica esposto dall’adattatore (setPublicKeyEncryption()), che delega al motore.

Il comportamento di cifratura riflette il gestore di sicurezza standard descritto in ISO 32000-2 §7. Tale clausola definisce le voci del dizionario di cifratura e il gestore standard AES-256 utilizzato dal motore. Questa documentazione non afferma che l’output sia «sicuro per impostazione predefinita» o «a prova di manomissione». Indica la cifratura utilizzata e il comportamento della password del proprietario, cioè ciò che il codice implementa. Il digest delle clausole fissate si trova nel front-matter della pagina, sotto citations.

examples/security-encryption.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, 'Encrypted document');
// User password set; owner password auto-generated (strong, random).
$pdf->SetProtection([], 'user-secret');
$pdf->Output(__DIR__ . '/encrypted.pdf', 'F');

Leggere questa sezione alla lettera. È volutamente conservativa.

  • I metodi legacy di TCPDF setSignature() e addEmptySignatureAppearance() non sono implementati nell’adattatore basato sul motore core. Non fanno nulla in modalità predefinita e sollevano TcpdfNotImplementedException in modalità strict.
  • La firma digitale non è una funzionalità della distribuzione core tramite questo adattatore. Il supporto alle firme baseline è riservato a un’edizione commerciale di NextPDF.
  • Dove è presente un’edizione commerciale, l’adattatore espone un moderno punto di ingresso per la firma (setSignatureV2()) che delega al motore. Il suo profilo predefinito è il profilo baseline (B-B).
  • Questa documentazione non afferma che alcuna edizione produca, tramite questo adattatore, profili di firma con marca temporale, a validazione a lungo termine o archivistici. In particolare, non attesta il comportamento B-T, B-LT o B-LTA. La specifica baseline PAdES §6.1 definisce quattro livelli baseline distinti — B-B, B-T, B-LT e B-LTA — ciascuno con i propri requisiti. B-B è il livello baseline, mentre i livelli superiori (marca temporale, lungo termine, archiviazione) sono profili distinti e più esigenti. Solo il baseline B-B rientra nell’ambito della documentazione di questo livello di compatibilità. I livelli superiori sono esplicitamente fuori ambito e non vengono dichiarati per alcuna edizione in questa sede. Il digest delle clausole fissate si trova nel front-matter della pagina, sotto citations.
  • In nessun punto viene dichiarata una firma «certificata», «garantita», «giuridicamente valida» o «qualificata eIDAS». La correttezza della firma, la policy degli anchor di fiducia e la validità giuridica sono responsabilità dell’edizione di firma e della PKI del chiamante, non di questo livello di compatibilità.

Se la migrazione richiede la firma, trattarla come un flusso di lavoro separato: adottare la moderna API di firma in un’edizione commerciale e validare la firma prodotta con un verificatore indipendente. Non fare affidamento sulla chiamata setSignature() di TCPDF: qui non ha alcun effetto.

Il metodo legacy setTimeStamp() è accettato per compatibilità della firma ed emette un avviso; non produce una firma con marca temporale tramite questo adattatore.

Il flag pdfa del costruttore è accettato per compatibilità con la firma del metodo. La conformità archivistica PDF/A richiede un’edizione commerciale di NextPDF. L’adattatore espone enablePdfA(), che delega al motore, e il motore restituisce un errore di configurazione esplicito e azionabile quando l’edizione richiesta è assente. L’adattatore non produce silenziosamente un file non conforme dichiarando che sia PDF/A.

L’output è sempre PDF 2.0 (ISO 32000-2). ISO 32000-2 §7.5.2 specifica che uno scrittore conforme identifica la versione del documento come 2.0 e non la abbassa a una versione precedente al salvataggio. setPDFVersion() non può quindi puntare a una versione precedente (vedere /integrations/tcpdf-compat/method-coverage/ §4). Il digest delle clausole fissate si trova nel front-matter della pagina, sotto citations.

  • Nessuna terminazione del processo. Poiché Error() solleva un’eccezione invece di die(), racchiudere i punti di ingresso del rendering in try/catch e mappare i guasti sul contratto di gestione degli errori dell’applicazione. Non dare per scontato che un rendering fallito ponga fine alla richiesta.
  • Sicurezza del buffer di output. Output() con S restituisce i byte; con F scrive un file; con E restituisce un corpo MIME in base64; con I/D instrada attraverso il percorso di output del motore. Preferire S o F nei worker e negli handler HTTP per mantenere il controllo diretto della risposta — vedere /integrations/tcpdf-compat/production-usage/.
  • La modalità strict non è un’impostazione di produzione. Limitarla a un job di CI/audit. Un’eccezione in un percorso di rendering di produzione è peggiore di un parametro degradato in modo silenzioso.
  • Igiene delle costanti. Definire le costanti PDF_* / K_* prima della prima costruzione dell’adattatore. I due flag irrobustiti (K_TCPDF_CALLS_IN_HTML, K_TCPDF_THROW_EXCEPTION_ERROR) non possono essere allentati; non tentare di farlo.
  • Password del proprietario casuali. Se si fa affidamento su una password del proprietario deterministica, impostarla esplicitamente. In caso contrario, per ciascun documento ne viene generata una casuale, robusta e non recuperabile.
  • Per i metodi relativi alle immagini, un percorso con stream wrapper viene rifiutato prima di qualsiasi lettura dal filesystem. Il rilevamento del tipo di immagine (TcpdfImages::getImageFileType) tratta qualsiasi percorso scheme://phar://, php:// e altri stream wrapper di PHP — come un wrapper e salta la sonda file_get_contents / getimagesize, ricorrendo a un’inferenza basata solo sull’estensione. Questo chiude un vettore di deserializzazione dei metadati phar sul target di backport per PHP 7.4; l’incorporamento dello stesso percorso wrapper viene rifiutato dal motore.
  • Per il resto, l’adattatore non convalida né sanifica i percorsi dei file passati ai metodi di immagine o di output oltre a quanto fa il motore. Considerare i percorsi e gli URL forniti dal chiamante come non attendibili al confine dell’applicazione.
  • L’HTML passato ai metodi HTML viene reso dal motore, non da un parser HTML di TCPDF. Il punto di esecuzione PHP legacy rimane chiuso, ma l’HTML fornito dal chiamante dovrebbe comunque essere trattato come input non attendibile.
  • La cifratura protegge la riservatezza del documento a riposo secondo il gestore standard. Non sostituisce la sicurezza del trasporto o il controllo degli accessi nell’applicazione.
  • /integrations/tcpdf-compat/method-coverage/ — comportamento esatto di SetProtection(), setSignature()
  • /integrations/tcpdf-compat/configuration/ — i due flag irrobustiti e non configurabili
  • /integrations/tcpdf-compat/production-usage/ — worker, buffer, gestione dei guasti
  • docs/TCPDF_COVERAGE.md — matrice di copertura autorevole
  • File NOTICE del pacchetto — dichiarazione di implementazione indipendente