PDFPipe

Document security / What is inside it

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.

The exposure

A document assembles data that is scattered in your system into one coherent, portable record. That is the point of it and also the exposure: an invoice carries a name, an address, a relationship, purchase history and amounts in a single file. Emailed, that file is on a mail server, in a backup, on a phone, possibly forwarded, and outside every control you have. The question worth asking before it goes is not whether the recipient is entitled to it, but whether every field on it needs to be there.

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 the minimum that makes the document do its job. A field is not free because it was already in the database.
  • Check what got included by inheritance. Templates accumulate fields, and a document showing an internal customer segment or a risk flag is disclosing something nobody chose to disclose.
  • Truncate identifiers rather than printing them in full where the full value is not needed, which is a well-established convention for exactly this reason.
  • Look at what is on the document as a whole rather than field by field, because the disclosure is the combination and each field looks harmless alone.
  • Prefer a link over an attachment where the content is sensitive, so the document stays on your side and can be withdrawn.
  • Never put anything on a document that you would not want the recipient to forward, because forwarding is the default behaviour and not an edge case.

In practice

A fragment, with the thing that goes wrong kept in a comment where it is the more instructive half.

js
/* The question is not "is the recipient entitled to this document"
   but "does every field on it need to be there". Templates accumulate
   fields, and nobody removes them.                                   */

// Scope explicitly rather than passing the record through.
function invoiceViewModel(invoice, customer) {
  return {
    number: invoice.number,
    issuedAt: invoice.issuedAt,
    total: invoice.total,
    lines: invoice.lines.map((l) => ({ desc: l.desc, qty: l.qty, amount: l.amount })),
    customer: {
      name: customer.name,
      address: customer.billingAddress,
      // Deliberately absent, and each was on the template once:
      //   segment            an internal classification
      //   riskScore          an internal judgement
      //   accountNotes       written by staff, about them
      //   dateOfBirth        never needed on an invoice
    },
    // Truncated, because the full value is not needed to identify it.
    accountRef: mask(customer.accountNumber),   // ****4471
  };
}

// Not this: the whole record reaches the template and the template
// decides. Any field added upstream appears on the document.
//   const html = template({ invoice, customer });

/* And the test that catches drift: assert the rendered text does not
   contain the fields that should never be on it.                     */
expect(await extractText(pdf)).not.toContain(customer.dateOfBirth);

What people do instead

Passing the whole record into the template and letting the template choose. Every field added upstream for an unrelated reason becomes available to the document, and one of them eventually gets rendered because it was convenient.

How this is found out

By a recipient noticing something about themselves that they did not expect you to have, or by a data protection review. Never by monitoring, because a document with an extra field is a perfectly successful render.

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.

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.