Security and operations — NextPDF on CodeIgniter 4
At a glance
Section titled “At a glance”This page describes the threats this integration must resist, the controls verified in the package source, and the operational rules you should follow for a safe deployment.
Threat model
Section titled “Threat model”You need to account for three attacker-influenced surfaces.
- Queue job payload. A queue stores job data. An attacker with broker access can change that data. Treat it as untrusted, deserialized input.
- Response filename. A user can supply the download filename. A malicious name can inject header content.
- Configuration paths. The font path and signing paths come from configuration. A malicious path can read from or write to the wrong location.
Control 1 — Queue payload allowlist
Section titled “Control 1 — Queue payload allowlist”The queue job treats its payload as untrusted deserialized data. The Open Worldwide Application Security Project (OWASP) Application Security Verification Standard (ASVS) requires safe input handling for deserialized untrusted data (ASVS V1.5.2).
Verified controls in GeneratePdfJob:
- The builder must be a non-empty string. The job rejects any other type.
- The builder must match the pattern
App\PdfBuilders\<Class>::<method>. The job rejects any other namespace, plain functions, and payloads with a prefix or suffix. - The builder must be callable. The job rejects a string that matches the pattern but does not resolve.
Together, these rules block arbitrary code execution through a tampered queue payload. The package tests assert each rejection case.
Control 2 — Queue output-path confinement
Section titled “Control 2 — Queue output-path confinement”The job writes a file to disk. OWASP ASVS requires safe path handling when an application creates file paths for file operations (ASVS V5.3.2).
Verified controls in GeneratePdfJob:
- The output path must be a non-empty string.
- The job normalizes the path before any check. It resolves
.and..segments and converts separators. - The normalized path must sit inside
WRITEPATH/pdfs/. The job rejects a sibling directory that shares a name prefix (pdfs-evil/). - The path must end with
.pdf(case-insensitive).
These rules block arbitrary file writes through a tampered payload.
Control 3 — Response header hardening
Section titled “Control 3 — Response header hardening”PdfResponse attaches a fixed, hardened header set to every Portable
Document Format (PDF) response:
| Header | Value |
|---|---|
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
Content-Security-Policy | default-src 'none' |
X-Robots-Tag | noindex, nofollow |
Referrer-Policy | no-referrer |
Cache-Control | private, max-age=0, must-revalidate |
The package sanitizes the filename before it reaches the header. It
strips path separators, null bytes, and carriage return/line feed
(CR/LF). It escapes double quotes for the quoted form. It adds a
Request for Comments (RFC) 5987 filename*=UTF-8''… parameter for a
non-ASCII name. An empty name becomes document.pdf.
Control 4 — Configuration path validation
Section titled “Control 4 — Configuration path validation”The font registry rejects a fontsPath value that contains a stream
wrapper (://) or a null byte. It raises a runtime error. This blocks
wrapped paths such as php:// or phar://.
Control 5 — Minimal service-locator surface
Section titled “Control 5 — Minimal service-locator surface”CodeIgniter 4 does not provide a PHP Standards Recommendation 11
(PSR-11) container. It uses a Services locator. PSR-11 §1.3 treats the
service-locator pattern as discouraged (modal SHOULD NOT). The package
keeps the locator surface small: each service has one named factory
method. Resolve services at the controller boundary. Pass concrete
objects inward. Do not pass the Services class into domain code.
Signing and TSA operations (NextPDF Pro / Enterprise)
Section titled “Signing and TSA operations (NextPDF Pro / Enterprise)”The signing service stays inactive by default. It activates only when
signature.enabled is true and signature.certificate is non-empty.
The package default signature level is B-B. NextPDF Pro provides the
B-B baseline signature. Long-term validation is a separate Enterprise
capability, documented in the Premium reference rather than here.
Operational rules:
- Keep certificate and key files out of source control. Supply them
through
.envor a secrets manager. - Keep
tsa.allow_insecure_httpset tofalsein production. A plaintext Time Stamping Authority (TSA) channel is not acceptable. - Set
tsa.pinned_public_keyswhen the TSA publishes a stable key. Keeptsa.warn_on_key_rotationset totrue. - Restrict read access on the key file to the application user.
Operations checklist
Section titled “Operations checklist”- Pin all resolved versions in
composer.lock. - Require
codeigniter4/queuein the application that runs workers. - Run the queue worker as a low-privilege user. Give it write access to
WRITEPATH/pdfs/only. - Give the worker the same NextPDF extensions as the web tier. A signed PDF needs NextPDF Pro or Enterprise in the worker environment.
- Confirm that the
mbstringandzlibextensions are available in every runtime that builds a PDF. - Confirm that the response headers survive the reverse proxy.
- Log PDF generation with context. Do not log certificate material or key passwords.
Conformance
Section titled “Conformance”- Queue payload handling aligns with OWASP ASVS V1.5.2.
- Queue output-path handling aligns with OWASP ASVS V5.3.2.
- The locator design follows PSR-11 §1.3 guidance.
Commercial context
Section titled “Commercial context”NextPDF core is licensed under Apache-2.0. Signature trust anchors and TSA hardening apply when NextPDF Pro or Enterprise is installed. The CodeIgniter package exposes the corresponding service methods, which return null until the matching Premium package is installed. See </get-license/?intent=codeigniter-signing>.
See also
Section titled “See also”- /integrations/codeigniter/production-usage/ — correct queue registration and dispatch.
- /integrations/codeigniter/configuration/ — signing, TSA, and path keys.
- /integrations/codeigniter/troubleshooting/ — verified rejection messages.
- /integrations/codeigniter/overview/ — full API surface.