---
name: document_release_leak_check
description: "Check a finished PDF or DOCX before it leaves the building: scan the final file for hidden and invisible text, tracked changes and comments, embedded files, macros and scripts, leftover placeholders, metadata that names people, companies or local paths, and a named term sweep for the words that must not ship, then fix in leak risk order and verify the clean copy that will actually be sent. Ships a tested stdlib scanner and a release checklist. Use when a document is about to be emailed, filed, published or handed to a client, counterparty, board or regulator, when a redacted or sanitized copy needs proving, or when a document that looks clean needs a hidden layer check."
---

# Document Release Leak Check

## Purpose

Check the exact file that is about to leave, not the draft you remember cleaning. A finished document can look clean on the page and still carry deleted text in its tracked changes, margin comments, whole embedded files, hidden text, and properties that name the people who wrote it and the folders it lived in. This skill runs a scanner over the file structure, orders the fixes by how badly each one leaks, walks through the cleanup routes in Word and Acrobat, and finishes by rescanning the clean copy and looking at its rendered pages.

The scanner is Python standard library only. It reads a DOCX as the zip package it is and a PDF as objects and content streams, decompressing FlateDecode streams itself. No install step and no document leaves the machine.

## Workflow

### 1. Freeze the release copy and build the term list

- Work on a copy named for the release. Keep the original in the job folder. Fixes, exports and rescans all happen on the copy.
- Write the must-not-ship term list before scanning: internal project and codenames, private client or counterparty names, people names that stay internal, salary or price detail that was cut, unreleased dates. Add spelling variants and short forms. One term per line in a text file, or repeat `--term` on the command line.
- Note the file name itself as part of the check. A name carrying a codename, a person or the word draft leaks before the file is opened.

### 2. Scan the file that will be sent

```
python3 ~/workspace/skills/document-release-leak-check/scripts/leak_scan.py release.docx --terms-file terms.txt --json report.json
python3 ~/workspace/skills/document-release-leak-check/scripts/leak_scan.py release.pdf --terms-file terms.txt --json report.json
```

- Read the whole report, worst first. Severity runs CRITICAL, HIGH, MEDIUM, LOW, INFO. The run exits 1 when any finding sits at or above the fail threshold, which defaults to HIGH, and 0 when the file is clean at that threshold. `--fail-on medium` tightens a release that also wants the metadata gone.
- Scan each format you will send. A clean DOCX proves nothing about the PDF exported from it, and converting Word to PDF does not remove metadata on its own.
- Run the scanner selftest once on a new machine or after any edit to the script: `python3 ~/workspace/skills/document-release-leak-check/scripts/leak_scan.py --selftest`. It builds a planted DOCX and PDF and a clean pair, and it must report 17 of 17 passed before you trust a scan from it.

### 3. Read the findings by family

- Tracked deletions (CRITICAL): deleted text stays in a DOCX until the change is accepted or rejected. The scanner prints the deleted text it found. Treat any hit as content the recipient can read.
- Embedded files and code (CRITICAL): embedded objects inside a DOCX, attachments inside a PDF, a VBA macro project, PDF JavaScript and open actions. None of these show on the page.
- Banned terms (CRITICAL): every hit prints the surrounding text. Decide whether the term itself is the leak or a sign that a whole paragraph is internal.
- Comments, tracked insertions and moves (HIGH): discussion and half decided edits. Hiding markup never removes any of it.
- Hidden and invisible text (HIGH): Word runs formatted hidden, and PDF text drawn in render mode 3, which draws nothing and still extracts. PDF layers set OFF and annotation text also land here or just below.
- Placeholders (HIGH): TODO, TBD, bracketed insert notes, template braces, filler text and the word DRAFT on a final copy.
- Metadata (MEDIUM and LOW): DOCX core properties name the creator and the last person to save the file, app properties can name a company, a manager and a template path on a local machine, and PDF Info and XMP fields name authors and creators. Revision counts and editing time ride along at LOW.
- Structure notes (MEDIUM and LOW): a PDF with several end of file markers was updated incrementally and can still hold earlier object versions. Form fields and custom properties can hold values that never show on a page.

### 4. Fix on the copy, in leak risk order

- Follow `references/release-checklist.md`, which orders the work: unseen content first, then the words that must not ship, then metadata, then structure.
- Decide tracked changes, do not just accept them blind. Accepting a deletion removes the text for good, and rejecting an insertion removes text someone may have meant to keep. Read the scanner excerpts, decide, then settle every change.
- Delete comments, hidden runs, embedded files, annotations and scripts from the copy. Never fix hidden content by covering it, recoloring it or painting a shape over it. Covered text stays in the file and stays copyable.
- Clean DOCX properties on the copy with File, then Info, then Check for Issues, then Inspect Document in Word for Windows, reviewing each category before removing it. Word for Mac and Word on the web do not have the same inspector, so clear properties there by hand and let the rescan be the proof.
- Clean a PDF in Acrobat Pro with All tools, then Redact a PDF, then Sanitize document, choosing Remove all or the selective categories the release needs. Without Acrobat, produce the PDF again from the cleaned source and rescan it, and say plainly which metadata fields remain if any do.
- Clear placeholders by finishing the document, not by deleting the marker and leaving the gap.

### 5. Verify the clean copy three ways

- Rescan the exact release file with the same term list. Release needs no CRITICAL and no HIGH finding. Any LOW or INFO finding left standing gets named in the report with the reason it is safe to keep, such as a public title in the properties.
- Search the term list once by hand in the extracted text of the clean copy. The scanner searches extracted text too. A second pass catches text stored in an encoding one reader handles differently from another.
- Render or open every page of the clean copy and look at it. Confirm no page vanished in cleanup, nothing sits under a shape that should have been deleted, and the document still reads as the finished document.
- Check the scanner limits before signing off. It does not OCR scanned page images, so text inside a scanned image is checked by eye only. It flags a white fill operator in a PDF as possible white text at MEDIUM because white text on a dark shape is normal design. It reads FlateDecode streams and uncompressed streams, so text in other filters or in encrypted files is outside its view, and an encrypted file gets reported as the gap it is rather than passed.

### 6. Send and keep the evidence

- Send the verified copy, under its release name.
- Keep the term list, the final scan report and the name of the file sent in the job folder. The next release of the same document starts from that list instead of from memory.

## Output Contract

A finished check delivers:

- The release file, rescanned after its fixes, with no CRITICAL and no HIGH finding at the default threshold.
- The scan report for the exact file sent, as printed output or the JSON file from `--json`, plus the term list used.
- A short release note: file name sent, format, findings fixed by family and count, any LOW or INFO findings left standing with the reason, and a line confirming the rendered pages were looked at.
- A plain statement of anything the check could not cover, such as scanned image pages that were read by eye only or an encrypted source that could not be scanned.

## Operating Rules

1. Scan the file that will be sent, in the format it will be sent in. A check on an earlier draft or a different export is not a check on the release.
2. Never present hiding as removing. No Markup view, a black rectangle, white text and a switched off layer all leave the content in the file.
3. Fix on a copy and keep the original. Inspector and sanitize removals cannot always be undone, and the original is the only route back.
4. Deleted text is real text until the change is settled. If the scanner can print it, so can the recipient.
5. The term list belongs to the release, not to the scanner defaults. A scan run with no terms only proves the structural checks passed. Say so in the release note when no list was supplied.
6. Do not loosen the fail threshold or drop a finding to make a release pass. Fix the file, or report the finding and let the sender decide with it in front of them.
7. A clean scan is evidence about the checks the scanner runs, not a promise that a document holds nothing sensitive. Visible body text still gets read by a person before release. The scanner never replaces reading the document.
8. Keep scan reports inside the job. A report quotes the leaked text it found, so the report itself is internal material.
