Release note · August 6, 2026
A regression gate cannot see an already stale signature boundary
PDFFence 1.17 made one useful condition review-visible: a semantic PDF signature's /ByteRange used to reach the file end and no longer does after a comparison. That is a regression question. But serious review workflows often begin after history has already accumulated. If both sides already have a signature range behind their current physical file end, a regression-only rule correctly sees no new drop—and leaves the missing current boundary unreported.
The question a baseline cannot answer
A PDF can gain incremental revisions for many reasons. The PDF 2.0 signature guidance describes a signature's byte-range boundary for the incremental revision that adds it; later signatures, timestamps, or other updates complicate any validity decision. The key static question here is narrower: if a document has a standard semantic signature root, is there at least one corresponding well-formed range that reaches the current stored file end?
PDFFence still establishes a root only through a catalog-reachable AcroForm signature field, including inherited /FT, or catalog /Perms DocMDP, UR, or UR3. An arbitrary private /PieceInfo dictionary that looks like /Type /Sig does not meet that test.
PFP010: require a current boundary when signatures exist
PDFFence 1.18 adds the opt-in require_current_file_signature_coverage rule, PFP010. It fails only when an inspected PDF has one or more semantic signature roots and none of their ByteRanges reaches the current physical file end. An unsigned PDF passes: the rule does not demand that every document be signed.
This makes PFP010 complementary to PFP009, not a replacement. PFP009 answers “did current coverage fall?” PFP010 answers “is any current coverage present now?” A team can use the latter where it receives PDFs without a known-good predecessor and wants a generic review gate for an already-stale boundary.
version: 1
rules:
require_current_file_signature_coverage: true
A control with no coverage delta
PDF Change Assurance Benchmark 1.18.0 adds a deterministic pair for exactly that distinction. Its baseline already contains a semantic field-root ByteRange before the current file end. The candidate appends another distinct incremental revision, but both aggregate coverage counts remain zero. The expected public changes are only the revision-chain and stored-byte signals; PFP009 has no regression to report, while PFP010 is the single policy finding.
The PDF 2.0 signature errata and the PDF Association's signature-vulnerability advisory motivate why byte-range boundaries deserve explicit review. They also make the limit clear: a static boundary is not a cryptographic verdict.
Scope and validation
PFP010 can flag a later update that a conforming signature validator may consider acceptable. PDFFence does not locate or validate /Contents, calculate a signed digest, validate certificates or trust chains, inspect transforms or permissions, or decide that an update is valid, permitted, safe, or malicious. It reports only aggregate counts and generic findings.
PDFFence passed 235 tests and Ruff; PDFCAB passed 85 tests and Ruff. The source candidate scores all 155 benchmark pairs. Two fixed-timestamp builds of both packages were byte-for-byte reproducible and passed Twine metadata checks. Clean paired wheel installs on Python 3.12 and 3.13, plus a clean paired Python 3.12 source-archive install, passed dependency checks, fixture verification, and the complete 155-pair score.
The tagged policy reference, threat model, and validation record define the supported boundary.
python -m pip install https://github.com/SybilGambleyyu/pdffence/releases/download/v1.18.0/pdffence-1.18.0-py3-none-any.whl
pdffence check before.pdf after.pdf --policy pdffence.yml --format sarif
PDFFence is MIT-licensed and available on GitHub. The release assets include SHA-256 checksums for the wheel and source archive.