Skip to content
GitHubOpen source
Product
Docs
Solutions
IndustriesAll industries
CompareCompare all AI data-leak tools
Benchmarks
GitHubApache-2.0

File masking

Prompts are not the only way data reaches a model. Files uploaded for retrieval, attached to a message or embedded as base64 often carry far more sensitive content than the prompt itself. Shadow masks them before they leave the machine.

TransportExamples
multipart/form-data uploadsOpenAI POST /v1/files, POST /v1/uploads parts
Base64 files inside JSONOpenAI input_file.file_data, Anthropic document blocks with a base64 source, Gemini inline_data
data: URIsdata:text/csv;base64,... anywhere in a JSON string

The format is recognised from the declared MIME type and the file name.

FormatTreatmentResult
Plain text, MarkdownMasked as textSame file, masked
CSVMasked as text, cell by cellSame columns and rows
JSONMasked as JSON (string values)Valid JSON
HTML, XMLMasked as textMarkup intact
DOCXMasked in place: the document’s text runsA valid Word document
XLSXMasked in place: shared stringsA valid workbook; numbers and formulas untouched
PPTXMasked in place: text runs on slidesA valid presentation
PDFText is extracted, masked and sent as text (pdf = "text")The model receives the masked text instead of the PDF
ImagesPassed through unchanged by default (images = "pass")No OCR yet
Anything elsePassed through

Masking uses the same detectors, persona, vault and intent policy as prompts, so a customer named in the prompt and in an attached spreadsheet gets the same fake in both. A customer list attached to a report request gets typed tokens.

Office documents are edited inside their ZIP container, so styles, tables and layout survive. A value split across differently formatted runs (for example a name that is half bold) may not be recognised.

PDFs cannot be safely edited in place, so Shadow offers three choices:

pdf =Behaviour
"text" (default)Extract the text, mask it, send it as a text document. Layout, images and scanned pages are lost
"block"Refuse the request with an error, so a PDF never leaves unmasked
"pass"Send the PDF unchanged (not masked)

Shadow does not run OCR yet. Images, including screenshots and scanned documents, are passed through unchanged by default. If images may contain sensitive data, block them:

[files]
images = "block"
[files]
enabled = true # mask uploaded files (default true)
pdf = "text" # text | block | pass
images = "pass" # pass | block
max_bytes = 52428800 # 50 MiB; larger files are not masked
  • No OCR. Text inside images and scanned PDFs is not detected.
  • PDF layout is not preserved in text mode. Questions about the visual layout of a PDF will get worse answers.
  • Files above max_bytes are forwarded unmasked with a warning, or refused when block_oversize = true.
  • Uploads by reference. A file already uploaded to the provider earlier (by file_id) is not re-scanned. Upload files through Shadow from the start.
  • Embedded objects in Office files (charts’ cached values, embedded workbooks, images) are not masked.
  • Archives (.zip, .tar) other than Office formats are passed through.

Check what Shadow finds in a document’s text with shadow scan on an exported text version before you rely on it.