Praktik Terbaik Keamanan
Panduan ini memberikan rekomendasi keamanan yang actionable untuk men-deploy TCPDF-Next di lingkungan produksi. Mengikuti praktik ini memastikan pipeline pembuatan PDF Anda memenuhi standar keamanan enterprise.
Validasi Input (Sanitisasi HTML Sebelum writeHtml)
Saat membuat PDF dari HTML yang diberikan user, selalu sanitasi input sebelum meneruskannya ke HTML renderer. HtmlRenderer TCPDF-Next mem-parse dan me-render HTML dengan tepat, yang berarti markup berbahaya dapat dieksploitasi jika tidak disanitasi.
use YeeeFang\TcpdfNext\Html\HtmlRenderer;
// BERBAHAYA: Jangan pernah kirim input user mentah secara langsung
// $renderer->writeHtml($userInput);
// AMAN: Sanitasi dulu dengan library khusus
$clean = \HTMLPurifier::getInstance()->purify($userInput);
$renderer->writeHtml($clean);Aturan utama:
- Hapus tag
<script>,<iframe>,<object>,<embed>, dan<link>sebelum rendering. - Hapus skema URI
javascript:dandata:dari atributhrefdansrc. - Batasi properti CSS yang diizinkan pada yang dibutuhkan untuk layout (tanpa
position: fixed, tanpaurl()di nilai CSS). - Validasi encoding karakter — pastikan input adalah UTF-8 yang valid sebelum dikirim ke renderer.
Manajemen Sertifikat (Penyimpanan dan Rotasi Aman)
Hierarki Penyimpanan
| Metode | Level Keamanan | Use Case |
|---|---|---|
| Hardware Security Module (HSM) | Tertinggi | Lingkungan produksi, industri teregulasi |
| Cloud KMS (AWS KMS, Azure Key Vault, GCP KMS) | Tinggi | Deployment cloud-native |
| File PKCS#12 dengan passphrase kuat | Sedang | Deployment kecil |
| File PEM (terenkripsi) | Sedang-Rendah | Development, testing |
| File PEM (tidak terenkripsi) | Terendah | Jangan pernah di produksi |
Kebijakan Rotasi
- Perbarui sertifikat minimal 30 hari sebelum kedaluwarsa.
- Pantau kedaluwarsa dengan alert otomatis di ambang batas 30, 14, 7, dan 1 hari.
- Cabut sertifikat yang dikompromikan segera via CA penerbit.
- Pertahankan log audit bertanda tangan dari semua operasi siklus hidup sertifikat.
use YeeeFang\TcpdfNext\Certificate\CertificateStore;
$store = new CertificateStore();
$store->loadFromDirectory('/etc/tcpdf-next/certs/', '*.pem');
$activeCert = $store->getActiveCertificate('document-signing');
if ($activeCert->getExpirationDate() < new \DateTimeImmutable('+30 days')) {
$logger->warning('Signing certificate expires soon', [
'subject' => $activeCert->getSubject(),
'expires' => $activeCert->getExpirationDate()->format('Y-m-d'),
]);
}DANGER
Jangan pernah menyimpan private key di repository source code, file tidak terenkripsi di filesystem bersama, kolom database tanpa enkripsi at rest, atau file log.
Penanganan Password (SASLprep dan Password Kuat)
Saat mengatur password enkripsi PDF, terapkan normalisasi Unicode via SASLprep (RFC 4013) untuk memastikan pemrosesan password yang konsisten di seluruh platform:
// TCPDF-Next secara otomatis menerapkan SASLprep ke password
$pdf->setEncryption()
->setAlgorithm(EncryptionAlgorithm::AES256)
->setUserPassword('pässwörd-with-ünïcöde') // SASLprep dinormalisasi secara internal
->setOwnerPassword($strongOwnerPassword)
->apply();Rekomendasi kebijakan password:
- Minimal 12 karakter untuk password user, 20 karakter untuk password owner.
- Gunakan generator acak yang aman secara kriptografis untuk password owner (
random_bytes()). - Jangan pernah hardcode password di source code — muat dari variabel lingkungan atau secret manager.
- Bersihkan password dari memori setelah digunakan dengan
sodium_memzero().
Pencegahan SSRF (Validasi URL untuk Gambar, TSA, OCSP)
TCPDF-Next memblokir SSRF secara default, tetapi Anda harus mengonfigurasi allowlist untuk resource eksternal yang sah:
use YeeeFang\TcpdfNext\Security\NetworkPolicy;
$networkPolicy = NetworkPolicy::create()
->denyPrivateNetworks() // Blokir 10.x, 172.16.x, 192.168.x
->denyLoopback() // Blokir 127.0.0.1
->denyLinkLocal() // Blokir 169.254.x
->allowDomain('cdn.yourcompany.com') // Gambar
->allowDomain('timestamp.digicert.com') // TSA
->allowDomain('ocsp.digicert.com') // OCSP
->setMaxRedirects(3)
->setRequestTimeout(10);
$pdf = PdfDocument::create()
->setNetworkPolicy($networkPolicy)
->build();Checklist:
- Validasi semua URL sebelum fetch (skema, host, port).
- Allowlist secara eksplisit domain TSA dan OCSP responder.
- Blokir skema
file://,gopher://,ftp://, dan non-HTTP(S) lainnya. - Log semua request yang diblokir untuk monitoring keamanan.
Validasi Path File (Cegah Path Traversal)
Saat menerima path file dari user (misalnya, untuk file font, gambar, atau tujuan output):
use YeeeFang\TcpdfNext\Security\ResourcePolicy;
$resourcePolicy = ResourcePolicy::strict()
->allowLocalDirectory('/app/public/assets/')
->allowLocalDirectory('/app/storage/fonts/')
->denyAllRemote();
$pdf = PdfDocument::create()
->setResourcePolicy($resourcePolicy)
->build();Aturan:
- Jangan pernah menggabungkan input user langsung ke path file.
- Resolve path ke bentuk kanonik absolut dan validasi terhadap direktori yang diizinkan.
- Tolak path yang berisi
.., null byte, atau karakter non-printable. - Gunakan
ResourcePolicy::strict()di produksi — ini menolak semua akses secara default.
Keamanan Deployment (Docker dan Izin File)
Konfigurasi Docker
FROM php:8.5-fpm-alpine
# Jalankan sebagai user non-root
RUN addgroup -S tcpdf && adduser -S tcpdf -G tcpdf
USER tcpdf
# Nonaktifkan fungsi PHP yang berbahaya
RUN echo "disable_functions = exec,passthru,shell_exec,system,proc_open,popen" \
>> /usr/local/etc/php/conf.d/security.ini
# Filesystem read-only (mount volume writable secara eksplisit)
# docker run --read-only --tmpfs /tmp ...Izin File
# Direktori sertifikat: hanya bisa dibaca oleh user web server
chown -R www-data:www-data /etc/tcpdf-next/certs/
chmod 700 /etc/tcpdf-next/certs/
chmod 600 /etc/tcpdf-next/certs/*.p12
chmod 600 /etc/tcpdf-next/certs/*.pem
# Direktori output: hanya bisa ditulis oleh user web server
chown -R www-data:www-data /var/lib/tcpdf-next/output/
chmod 700 /var/lib/tcpdf-next/output/
# Direktori temporary: writable, tidak world-readable
chown -R www-data:www-data /tmp/tcpdf-next/
chmod 700 /tmp/tcpdf-next/Content Security Policy untuk PDF yang Ditampilkan di Browser
Saat menyajikan PDF inline di browser, atur HTTP header yang sesuai untuk mencegah serangan embedding:
return response($pdf->toString(), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="document.pdf"',
'Content-Security-Policy' => "default-src 'none'; plugin-types application/pdf",
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'DENY',
'Cache-Control' => 'no-store, no-cache, must-revalidate',
]);Untuk PDF yang berisi data sensitif, lebih baik gunakan Content-Disposition: attachment untuk memaksa download alih-alih rendering di browser.
Rekomendasi Audit Logging
Konfigurasikan audit logging komprehensif untuk semua operasi PDF yang sensitif keamanan:
use YeeeFang\TcpdfNext\Security\AuditLogger;
AuditLogger::configure([
'channel' => 'tcpdf-security',
'log_signing' => true,
'log_encryption' => true,
'log_validation' => true,
'log_key_access' => true,
'log_tsa_requests' => true,
'log_resource_access' => true, // Log pemuatan gambar/font
'log_blocked_requests' => true, // Log pemblokiran SSRF
'redact_sensitive' => true, // Redaksi password/key dari log
]);Pantau untuk:
- Upaya validasi tanda tangan yang gagal (kemungkinan manipulasi dokumen).
- Warning kedaluwarsa sertifikat.
- Kegagalan komunikasi TSA.
- Volume signing yang tidak biasa (kemungkinan key compromise).
- Upaya SSRF yang diblokir (kemungkinan probing serangan).
- Pemuatan resource dari path yang tidak diharapkan.
Prinsip Least Privilege untuk Izin PDF
Saat mengatur izin dokumen PDF, berikan hanya akses minimum yang diperlukan:
use YeeeFang\TcpdfNext\Encryption\Permissions;
// RESTRIKTIF: Dokumen read-only
$pdf->setEncryption()
->setPermissions(Permissions::ACCESSIBILITY) // Hanya akses screen reader
->setUserPassword('reader')
->setOwnerPassword($strongOwnerPassword)
->apply();
// SEDANG: Dokumen yang bisa dicetak
$pdf->setEncryption()
->setPermissions(
Permissions::PRINT_HIGH_QUALITY
| Permissions::ACCESSIBILITY
)
->apply();
// HINDARI: Memberikan semua izin menggagalkan tujuan enkripsi
// Permissions::ALL tersedia tetapi jarang harus digunakanPanduan izin:
- Jangan pernah berikan
MODIFY_CONTENTSkecuali penerima perlu mengedit dokumen. - Selalu berikan
ACCESSIBILITYuntuk kompatibilitas screen reader (persyaratan hukum di banyak yurisdiksi). - Gunakan
PRINT_HIGH_QUALITYalih-alihPRINT_LOW_QUALITYkecuali Anda memiliki alasan spesifik. - Dokumentasikan alasan untuk setiap izin yang diberikan di kode Anda.
Bacaan Lanjutan
- Ikhtisar Keamanan -- Arsitektur keamanan dan filosofi desain
- PAdES B-LTA -- Level tanda tangan dan implementasi
- Enkripsi Lanjutan -- Persyaratan algoritma