github razvandimescu/gopdf v0.10.0
v0.10.0 — true redaction

latest releases: v0.11.2, v0.11.1, v0.11.0...
one month ago

release fractal

🌀 Release fingerprint — v0.9.6..v0.10.0

2 commits · 1 contributor(s) · +2180/-108 across 12 files · 2026-08-20 → 2026-08-20

🎨 Generated from this release's commit signal — how it's made →

Editor.RemoveText and Editor.RemoveRegion delete glyphs from the content stream rather than covering them.

ed := pdf.NewEditor(data)
ed.RemoveText("Confidential")          // the glyphs are gone from the output
ed.RedactText("Confidential", 0, 0, 0) // and a black box marks where they were

Two primitives rather than one call with a flag: deleting bytes and painting a rectangle are different operations, and composing them reads better than a boolean. RedactText keeps its old, honest behaviour — it draws a rectangle and leaves the text in place.

Surviving text does not reflow. Each removed run leaves behind a kerning number worth exactly the advance it had, so what follows stays where the reader last saw it.

What is scrubbed

Page content stream glyphs and text inside the Form XObjects those pages draw. Nothing else in the file: not annotations, form fields, the info dictionary, XMP metadata, or embedded files. The full table is in the README and in the godoc for RemoveRegion. This is deliberately narrower than "secure redaction" — a document can carry the same string in half a dozen other places, and which of them matter is yours to judge.

How it is verified

Matching is against the glyphs, not against a rectangle. Page.Search locates text by dividing a span's width evenly among its characters, which drifts in any proportional font; removing the wrong character while leaving the right one is worse than not removing at all.

The test suite redacts a corpus of real PDFs from assorted producers and reads the output back with MuPDF and Poppler, which share no code with gopdf or with each other. Reading it back with gopdf alone would only show that its writer and its reader agree.

Fixes that change existing behaviour

  • Editor.Apply no longer writes an orphan copy of each edited page's original content stream. Output is smaller — and anyone already using RedactText was shipping files whose original text sat in the output as an unreferenced object, readable by anything that walks the xref.
  • A TJ displacement now travels through the text matrix, as glyph advances already did. Extraction placed text after a kern incorrectly wherever a Tm carried a scale.
  • /Rotate values below zero normalise, so -90 reads as 270.

Extraction also got its speed back: recording glyph positions had made the shown string escape to the heap on every text-showing operator, costing an allocation per string on a path that was allocation-free. It now pays for that only when something is recording.

No public symbols were removed.

Full changelog: v0.9.6...v0.10.0

Don't miss a new gopdf release

NewReleases is sending notifications on new releases.