Changelog
All notable changes to lint-pdf are documented here. Format loosely
follows Keep a Changelog; versions use
PEP 440 (beta tags 0.1.0bN).
[Unreleased]
Section titled “[Unreleased]”- GS1 Digital Link structural policy (
CodexGs1DigitalLinkAnalyzer→CODEX_GS1_DIGITAL_LINK). Reads codex’sdetected_barcodes[].digital_linksyntactic validation facts (codex >= 1.29.0) and emits one finding per structural defect, severity banded per failure class — bad GTIN check digit / invalid primary / no primary key = error; un-padded GTIN (GS1 Sunrise-2027) / illegal-or-misordered key-qualifier / malformed AI = warning; deprecated convenience-alpha = advisory. Overridable per run viactx.config["gs1_digital_link_severities"]. Mirrors theCODEX_BARCODE_GRADEreader pattern (codex = facts, lint = policy); self-skips when the signal is absent (codex < 1.29.0, 1D symbols, marketing URLs), never raises. Validates GS1 Digital Link structure — not a GS1 certification, not URI resolution.
- The codex floor pin was bumped to
codex-pdf>=1.29.0(2026-06-18) now that codex 1.29.0 — which first emits thedigital_linkblock — is published to PyPI, so the signal is contractually guaranteed present. (The reader still self-skips defensively when the block is absent.)
[0.1.0b35] - 2026-06-04
Section titled “[0.1.0b35] - 2026-06-04”Security
Section titled “Security”- XXE hardening (external XML imports + JDF): the PitStop, callas,
Acrobat, custom, format-detect, and JDF parsers now parse via
defusedxml.ElementTreeinstead of the stdlibxml.etree.ElementTree, blocking external-entity and entity-expansion (“billion laughs”) attacks on attacker-supplied preflight reports. Drop-in: thefromstring/parse/ParseErrorsurface is unchanged. - SSRF scheme allowlist: the warm-on-need probe (
warming/registry.py) now rejects non-http(s)probe targets before opening a connection. The operator-run audit/seed scripts validate request schemes through a shared_checked()guard. - Corrected an ineffective
# nosemgrepsuppression in the fastText language-model download (was on the wrong physical line, so it never suppressed) and justified it inline — the URL is a hardcoded constant. - Bumped
defusedxmlfloor to>=0.7.1. - Added a blocking
securityCI job (semgrep--error+ bandit medium/medium) and pinned every workflow to least-privilegepermissions: contents: read.
- Reconciled the version skew between
pyproject.toml(0.1.0b34) andsrc/lintpdf/__init__.py(0.1.0b33); both now report0.1.0b35.