Document security / Who can reach the document
What belongs in a document filename, and what must not
The name the recipient sees, which travels further than the document's contents and is visible in places the contents are not.
The exposure
A filename is metadata that escapes. It appears in a mail client's attachment list, in a downloads folder, in a shared drive listing, in a backup index and in screen shares, and it is visible to people who never open the file. So a filename containing a customer name, an account number or a diagnosis discloses that to anyone who sees the listing. The opposite failure is equally common: every document called document.pdf, so a person with twenty of them in a folder cannot tell which is which.
The decisions
Reasons rather than a description of the code. Each one has a default that is fine for a page and wrong for a file somebody keeps.
- Include what identifies the document to its recipient and nothing that identifies a person. A document type, a reference and a date is usually the right shape.
- Never put a name, an account number, an email address or anything about the subject matter in the filename.
- Make it unique enough that a recipient saving several does not overwrite one with another, which is what happens when everything is called invoice.pdf.
- Keep it short and portable: no characters that need escaping, no leading dots, nothing that behaves oddly on a different operating system.
- Know what the API does with it: the filename you supply is sanitised, with control characters and quotes stripped, and truncated to 200 characters. That prevents header injection and does not make an unwise filename wise.
- Set the disposition deliberately rather than relying on a default, since inline and attachment produce different behaviour in the recipient's browser.
In practice
A fragment, with the thing that goes wrong kept in a comment where it is the more instructive half.
// Identifies the document, not the person.
function filenameFor(invoice) {
return `invoice-${invoice.number}-${format(invoice.issuedAt, "yyyy-MM")}.pdf`;
// invoice-2026-118-2026-03.pdf
}
/* Not any of these, all of which appear in a downloads folder, a mail
client's attachment list and a shared drive listing:
invoice-Wynne-and-Hall-Ltd.pdf the customer
statement-40129384.pdf the account number
results-a.patient@example.com.pdf the person
document.pdf indistinguishable from the
other nineteen
What the API does with the value you pass: control characters and
quotes are stripped and it is truncated to 200 characters, which
prevents header injection. It does not make a disclosing filename
safe: that is your decision, not a sanitiser's. */
const res = await pdf.post("/v1/pdf", {
html,
filename: filenameFor(invoice),
store: true,
});
// Set the disposition deliberately when you serve it onward.
res.setHeader("Content-Disposition",
`attachment; filename="${filenameFor(invoice)}"`);What people do instead
Putting the customer name in the filename to make support easier. It helps internally and it discloses the relationship to everyone who sees the recipient's screen, their downloads folder or their attachment list, none of whom opened the document.
How this is found out
Usually by somebody noticing during a screen share or a support call, which means it has been happening for as long as the feature has existed. There is no log line for a filename being visible.
Frequently asked
Does this page tell me what the law requires?
No, and deliberately not. Retention periods, erasure obligations and residency rules vary by jurisdiction, by industry and by the kind of document, and they change. What these pages describe is the shape of the problem and the mechanisms a system needs in order to implement whatever answer your own advisers give you. Where a genuine tension exists, such as an immutable record against a right to erasure, it is named as a tension rather than resolved.
Why is so much of this about the contents rather than access control?
Because access control decides who can obtain a copy and has no opinion at all about what happens to the copy. Once a document is on somebody's laptop, forwarded to a colleague or printed, every control listed here has already stopped applying to it. What is inside the file is therefore the part that keeps mattering, which is the opposite of the balance you would strike for a page.
How much of this applies at a small volume?
Most of it, because these are decisions rather than infrastructure. Redacting by omitting rather than covering costs nothing. Deciding what goes on a template costs one review. Classification is one object in code. Legal hold and an audit trail are the two that take real work, and both are far cheaper to build before they are requested than under the deadline that comes with the request.
Related security topics
The decisions that depend on each other, then the rest of the same group.
Serving a document so the browser treats it as a document
The headers that decide whether a file downloads, opens in a viewer, or is interpreted as something else entirely by a browser guessing at its type.
Personal data in a document that will be emailed
What a document discloses once it is attached to a message, which is more than the recipient asked for and travels further than the message.
What metadata a generated PDF carries, and how to check
The fields a document format carries alongside its visible content, which are invisible on the page and present in the file.
Serving a generated document behind proper access control
Making sure the person downloading a document is entitled to it, which fails most often because the document lives somewhere the check does not.
Signed URLs for documents, and choosing an expiry that fits
Giving out a URL that carries its own authorisation for a limited time, which moves the access check to the moment the link is minted rather than the moment it is used.
Every document security topic
The full list, grouped by access, contents and what happens afterwards.
What this API actually does
The options and endpoints these decisions are built on, one page each.
Most of these are decisions rather than features, and the cheapest time to make them is before the first document is delivered rather than after one reaches the wrong person.