compat-legacy security and operations
At a glance
Section titled “At a glance”The adapter uses the NextPDF engine’s security model and adds a few deliberate hardenings over legacy TCPDF 6.2.13. This page states exactly what is available and what is not, without overstatement. Read the signing section carefully; its scope is intentionally narrow.
Hardened legacy behaviors
Section titled “Hardened legacy behaviors”The adapter changes three historical TCPDF 6.2.13 behaviors for safety. They are not configurable back to the unsafe form:
| Concern | Legacy TCPDF 6.2.13 | Adapter |
|---|---|---|
| Error handling | Error() calls die() and terminates the process | Error() throws RuntimeException; callers can observe and catch the failure, with no silent process kill. |
| HTML execution | An escape hatch could run PHP from markup | The K_TCPDF_CALLS_IN_HTML constant is fixed to false; markup cannot trigger PHP execution. |
| Direct output | Output() echoes to the active output buffer | Output goes through a safe destination bridge and does not pollute a caller-controlled output buffer. |
The error-handling change ensures you can observe a failure instead of
losing the process to termination. Open Worldwide Application Security
Project (OWASP) Application Security Verification Standard (ASVS) 5.0
§16.5.3 states that an application should fail gracefully and securely
and prevent fail-open conditions. The throw-instead-of-die change
applies that principle. The HTML hardening removes a code-execution
sink. Treat legacy code that depended on the old behavior as a defect
to fix during /integrations/tcpdf-compat/migration/. The pinned clause
digest is in the page front-matter citations.
Encryption
Section titled “Encryption”The adapter exposes TCPDF’s SetProtection() and delegates to the
NextPDF engine’s standard security handler.
- The standard handler uses AES-256. The legacy
$modeparameter is accepted for method-signature compatibility and ignored; there is no way to select a weaker cipher through this method. When strict mode is on, a non-default$modethrows so the migration is forced to acknowledge it (asserted intests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php). - If no owner password is supplied, the adapter generates a cryptographically strong random owner password instead of reusing the user password. This prevents holders of user-level access from gaining owner-level control of the document.
- Certificate-based (public-key) encryption is not done through
SetProtection(); the adapter ignores its$pubkeysparameter. Use the modern public-key encryption entry point exposed on the adapter (setPublicKeyEncryption()), which delegates to the engine.
The encryption behavior reflects the standard security handler
described in ISO 32000-2 §7. That clause defines the encryption
dictionary entries and the AES-256 standard handler the engine uses.
This documentation does not claim the output is “secure by default” or
“tamper-proof”. It states only the cipher used and the owner-password
behavior implemented by the code. The pinned clause digest is in the
page front-matter citations.
<?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');Digital signatures — scope statement
Section titled “Digital signatures — scope statement”Read this section literally. It is deliberately conservative.
- The TCPDF legacy
setSignature()andaddEmptySignatureAppearance()methods are unimplemented in the adapter on the core engine. In default mode, they do nothing. In strict mode, they throwTcpdfNotImplementedException. - Digital signing is not a capability of the core distribution through this adapter. Baseline signature support requires a commercial NextPDF edition.
- If a commercial edition is present, the adapter exposes a modern
signature entry point (
setSignatureV2()) that delegates to the engine. Its default profile is the baseline (B-B) profile. - This documentation makes no claim that any edition produces
timestamped, long-term-validation, or archival signature profiles
through this adapter. Specifically, it does not assert B-T, B-LT, or
B-LTA behavior. The PDF Advanced Electronic Signatures (PAdES)
baseline specification §6.1 defines four distinct baseline levels:
B-B, B-T, B-LT, and B-LTA. Each has its own requirements. B-B is the
baseline level, and the higher levels (timestamp, long-term,
archival) are separate, more demanding profiles. Only the B-B
baseline is in scope for this compatibility layer’s documentation.
The higher levels are explicitly out of scope and are not claimed for
any edition here. The pinned clause digest is in the page
front-matter
citations. - This documentation makes no “certified”, “guaranteed”, “legally valid”, or “eIDAS-qualified” signature claim anywhere. Signing correctness, trust-anchor policy, and legal validity are the responsibility of the signing edition and the caller’s Public Key Infrastructure (PKI), not of this compatibility layer.
If your migration requires signing, treat it as a separate workstream:
adopt the modern signature application programming interface (API) on a
commercial edition and validate the resulting signature with an
independent verifier. Do not rely on the TCPDF setSignature() call;
it is a no-op here.
The legacy setTimeStamp() method is accepted for method-signature
compatibility and emits a notice; it does not produce a timestamped
signature through this adapter.
PDF/A and conformance
Section titled “PDF/A and conformance”The constructor’s pdfa flag is accepted for method-signature
compatibility. PDF/A archival conformance requires a commercial NextPDF
edition. The adapter exposes enablePdfA(), which delegates to the
engine, and the engine returns an actionable configuration error when
the required edition is absent. The adapter does not silently produce a
non-conformant file while claiming PDF/A.
Output is always PDF 2.0 (ISO 32000-2). ISO 32000-2 §7.5.2 specifies
that a conforming writer identifies the document version as 2.0 and
does not lower it to an older version on save. Therefore,
setPDFVersion() cannot down-target an older version (see /integrations/tcpdf-compat/method-coverage/
§4). The pinned clause digest is in the page front-matter citations.
Operational guidance
Section titled “Operational guidance”- No process termination. Because
Error()throws instead ofdie(), wrap render entry points intry/catchand map failures to your application’s error contract. Do not assume a failed render ends the request. - Output buffer safety.
Output()withSreturns bytes; withFwrites a file; withEreturns a base64 Multipurpose Internet Mail Extensions (MIME) body; withI/Dit routes through the engine output path. PreferSorFin workers and Hypertext Transfer Protocol (HTTP) handlers so you control the response yourself; see /integrations/tcpdf-compat/production-usage/. - Strict mode is not a production setting. Keep it to a continuous integration (CI) or audit job. An exception in a production render path is worse than a silently degraded parameter.
- Constant hygiene. Define
PDF_*/K_*constants before the first adapter construction. The two hardened flags (K_TCPDF_CALLS_IN_HTML,K_TCPDF_THROW_EXCEPTION_ERROR) cannot be relaxed; do not attempt to relax them. - Random owner passwords. If you rely on a deterministic owner password, set it explicitly. Otherwise, a strong random one is generated per document and is not recoverable.
Threat-model notes
Section titled “Threat-model notes”- For image methods, the adapter refuses a stream-wrapper path
before any filesystem read. Image type detection (
TcpdfImages::getImageFileType) treats anyscheme://path, includingphar://,php://, and other PHP stream wrappers, as a wrapper and skips thefile_get_contents/getimagesizeprobe, falling back to extension-only inference. This closes a phar metadata-deserialization vector on the PHP 7.4 backport target; the engine rejects the wrapper-path embed itself. - The adapter does not add path validation or sanitization for file paths passed to image or output methods beyond what the engine does. Treat caller-supplied paths and URLs as untrusted at your application boundary.
- HTML passed to the HTML methods is rendered by the engine, not by a TCPDF HTML parser. The legacy PHP-execution sink is closed, but you should still treat caller-supplied HTML as untrusted input.
- Encryption protects document confidentiality at rest under the standard handler. It is not a substitute for transport security or access control in your application.
See also
Section titled “See also”- /integrations/tcpdf-compat/method-coverage/ — exact behavior of
SetProtection(),setSignature() - /integrations/tcpdf-compat/configuration/ — the two hardened, non-configurable flags
- /integrations/tcpdf-compat/production-usage/ — workers, buffers, failure handling
docs/TCPDF_COVERAGE.md— authoritative coverage matrix- Package
NOTICE— independent-implementation statement