Redaction¶
Two passes: the submitter's, on their own device, before anything leaves it; and ours, on the homelab, before anything is extracted. The submitter's pass is the one that matters, because it is the only one that happens before the document crosses the internet.
Tool findings on this page are desk research dated 2026-10-23, checked against each project's release page. None has yet been tested on a real explanation of benefits; that is the open item at the bottom.
The one rule, stated first¶
Redaction must remove the text, not cover it. A highlight drawn over a PDF leaves the words underneath, selectable and searchable. A blur or mosaic can be reversed. Only an opaque fill, exported as a flat image, is safe. Then check it: zoom in, raise the brightness, and try to select text.
What to redact and what to keep¶
An explanation of benefits or itemized bill carries both the identifiers that must go and the figures the site needs.
| Redact | Keep |
|---|---|
| Patient and subscriber names, address, date of birth | Dates of service (we publish month and year only) |
| Member ID, group number, claim number, patient account number, document reference number | Procedure codes (CPT, HCPCS) with modifiers and units; revenue codes on facility bills |
| Names of individual clinicians and their NPIs and tax IDs (the rendering physician, the anesthesiologist, the radiologist) | The facility's name: the hospital, center, or lab. It identifies the facility, not you, and we need it. You also pick the facility from our list when you submit, which is how we match the bill when the document names a billing entity rather than the place |
| Billed, allowed, plan discount, plan paid, deductible, copay, coinsurance, not covered, patient responsibility | |
| Barcodes and QR codes, which usually encode the member or claim ID | Network status; plan name and type; remark and reason codes |
| Diagnosis codes, if the submitter prefers; we drop them anyway |
Submitter instructions, by device¶
Phone, the path most people will use¶
Take the photo or screenshot, open it in the phone's own editor, cover each identifier with a solid filled rectangle at full opacity, save as a copy, and share through a path that drops location data.
- iPhone. Use the Markup shape tool, filled, solid black. Do not use the marker or highlighter: it defaults to less than full opacity and the text underneath has been recovered by adjusting exposure (9to5Mac, 2018; MobileSyrup, 2019). When sharing, turn Location off under Options.
- Android, Google Photos. The Markup Redact pen added in September 2026 offers only mosaic and blur styles (9to5Google), which are the reversible kind. Use the plain pen at full opacity in a solid colour with overlapping strokes, or a filled shape, and save as a copy.
- Samsung One UI 8.5 and later. The share sheet's Privacy Protection detects sensitive text and offers redaction styles (SamMobile). Choose the solid style, not blur or pixelate.
- Krita on Android (krita.org, GPLv3) is the open-source phone editor the desk research turned up with a proper opaque-rectangle and flat export, for anyone who wants it; the survey was not exhaustive.
Unverified
Whether current iOS versions still default the marker to partial opacity; per-model availability of Samsung's Privacy Protection; whether iOS screenshots carry location metadata (camera photos do).
Desktop, the safest path¶
- Open the PDF or scan in LibreOffice Draw (MPL 2.0; 26.8.x as of October 2026) and use Tools → Redact, or Tools → Auto-Redact with text or regular-expression targets. Export only with Redacted Export (Black) or (White), which rasterizes the page so the text is gone. The toolbar's Direct Export to PDF is not a redaction; it keeps the text (LibreOffice help).
- Run the result through Dangerzone (Freedom of the Press Foundation, AGPLv3, v0.11.1 of 2026-10-22; Windows, macOS, Linux; needs Docker Desktop or Podman). It renders every page to pixels in a sandbox and rebuilds a new PDF, so nothing but the visible image survives (dangerzone.rocks). It is a flattener, not a redaction tool; it is the last step, not the first.
- Strip metadata with mat2 (LGPLv3+, 0.15.0; Linux and macOS, not Windows) or ExifTool (
exiftool -all=; all platforms). ExifTool's PDF metadata removal is reversible by design, so for PDFs prefer mat2 or qpdf after it (exiftool.org).
For an image rather than a PDF: GIMP (GPLv3, 3.2.6) with an opaque filled rectangle, exported as PNG or JPEG with every metadata checkbox unticked, then ExifTool.
Stirling-PDF (open-core; redaction tools are in the MIT part; v3.2.1 of 2026-10-21) is a reasonable alternative for someone who already runs Docker, with its Auto Redact in text-removal mode or the convert-to-image option ticked (releases). We could self-host an instance on the tailnet for volunteers; it is not a path to recommend to residents.
Browser-only tools¶
None recommended. The desk research found no open-source, audited, client-side-only PDF redactor; the closed ones it found make self-reported privacy claims, and at least one sends telemetry. That is a statement about what was found, not a survey of the market. Residents should use the phone or desktop paths above.
Failure modes to warn about¶
- Annotation-only boxes and highlights (Preview markup, Acrobat Reader comments, most phone PDF apps) sit on a layer above the text. The text stays selectable and the box can be deleted.
- Redaction that leaves the text layer: any tool that only draws a filled rectangle onto a PDF; LibreOffice's Direct Export; older Stirling manual redaction without image conversion. Flatten to an image after redacting.
- Semi-transparent markers: see iPhone above.
- Pixelation and blur are reversible. Depix (2020), Bishop Fox's Unredacter (2022), and UnPixel recover text from mosaic and Gaussian blur (BleepingComputer). Only opaque fills are safe.
- Cropping that did not crop. The 2023 aCropalypse bugs in Pixel Markup (CVE-2023-21036) and Windows Snipping Tool (CVE-2023-28303) left the original image bytes in the file. Patched, but files edited before the patch still leak.
- Metadata. Camera photos carry GPS, device serial, and timestamps; many editors keep them on export. Embedded EXIF thumbnails can hold the unredacted image. Strip with mat2 or ExifTool.
- Layered files. A rectangle on its own layer in XCF, KRA, PSD, or as a PDF annotation can be moved. Export flat.
Our pass¶
Every submission, redacted or not, goes through this on the homelab before anyone reads the figures.
| Stage | Tool | Notes |
|---|---|---|
| Rasterize | pdf2image or PyMuPDF at 300 dpi | Everything becomes pixels first, so a PDF text layer cannot leak past us |
| Strip metadata | mat2 | |
| OCR | Tesseract 5.5 (Apache-2.0); PaddleOCR 3.7 as fallback for phone photos | Tesseract is fast and strong on printed scans; PaddleOCR handles skew and photos better at higher compute |
| Detect identifiers | Presidio analyzer (MIT, now at data-privacy-stack/presidio) with spaCy en_core_web_trf or lg |
Built-in US_SSN, US_NPI, US_MBI, PHONE_NUMBER, EMAIL_ADDRESS, DATE_TIME, PERSON, LOCATION, CREDIT_CARD |
| Carrier patterns | Presidio PatternRecognizers |
Member ID, group, claim, and account numbers; see below |
| Barcodes | zbar via pyzbar | Detect and paint over; they encode IDs |
| Paint | Presidio image redactor | Boxes over every hit on the raster |
| Repository guard | GDD PII guard | Nothing personal reaches Git |
| Human look | The keeper | On the redacted raster and the extracted record, before anything is published |
| Delete | Scheduled | Originals gone after the deletion window; the record notes it |
spaCy's named-entity models are trained on prose; on upper-case tabular EOB text they miss names and mis-type providers, so names are one signal beside the regular expressions and label proximity ("Member ID", "Claim #"), never the only one. Presidio's context-aware scoring boosts a pattern hit sitting next to such a label.
Tools built for clinical narrative (Philter, NLM Scrubber, MIST) are dormant or closed-source and target the wrong document type. Cloud PHI detectors (AWS Comprehend Medical, Google DLP, Azure Language) would send a resident's bill to a third party, which the deletion promise rules out.
Carrier identifier formats¶
Publicly documented formats, for the pattern pass. The candidate design is a generic recognizer for an 8–17 character token next to a member, subscriber, group, claim, or account label, with the formats below as high-confidence matches. How much it catches and how much it flags wrongly are unmeasured until the sample run.
| Carrier | Format | Source |
|---|---|---|
| Horizon BCBSNJ | Three-character BCBS prefix, then 3HZN, then digits (YHV3HZN12345678) |
Horizon help center |
| Aetna | W + 9 digits, optional 2-digit dependent suffix (W123456789-01) |
Cornell HealthSafe ID guide |
| UnitedHealthcare | 9 digits, optional -00/-01 suffix; group 5–8 digits |
UHC sample card |
| AmeriHealth NJ | 12-digit unique member ID shared across a family; product prefixes Q1A, Q1B, Q1C, Q1H, Q1M and others | AmeriHealth hospital manual |
| Medicare | 11-character MBI; Presidio's US_MBI covers it |
Unverified
Cigna (secondary sources say U + 8 digits + 2-digit suffix), Oxford as distinct from UnitedHealthcare, whether AmeriHealth prints the prefix as part of the ID, NJ FamilyCare's 12-digit ID, every carrier's claim-number format, and the generic recognizer's recall and precision on real documents.
Open¶
- Test each submitter-side path above on a real EOB and an itemized bill, on an iPhone, an Android phone, and a desktop; then write the one-screen illustrated guide per device.
- Run Presidio with the carrier patterns on redacted and unredacted samples; record recall and precision per recognizer, with the false negatives and false positives listed. The numbers set triage order and what the reviewer is warned to look for; the human look before publication is mandatory whatever they say.
- Confirm the Cigna and Oxford identifier formats. Cigna first, from a volunteer's own card and explanation of benefits, used with their written consent and handled as any submission is: on the homelab, through the pass above, never in a third-party tool, Git, or anything published, deleted within the retention window. Only the format pattern is recorded; a committed test fixture is synthetic.