# Keep personal data out of your LLM prompts: redact before you send

- Author: RomanMotion (https://wurk.fun/user/RomanMotion)
- Published: 2026-11-04
- Canonical (HTML): https://wurk.fun/blog/keep-personal-data-out-of-your-llm-prompts-redact-before-you-send
- Cover image: https://ik.imagekit.io/wurk/browser-uploads/f1c626b5c17e7f0a61dfbbe7a20d85ae7b33a20527243aeec2ee1d0a8b87562a/68a1dcc2-8ca3-4ad2-8c8d-215d8d71b983/cover-pii.jpg?wurkUpload=v1.PLoGxzWAUKExBZsQ78ltxxK3TZqgFNFWVo1l71bijpA

---

Your app asks an LLM to summarize a support ticket, so your coding agent sends the whole customer record. That can expose a customer’s contact details or a secret to a provider that doesn’t need them. A small redaction step helps you keep useful context while sending less sensitive data.

Start by choosing only the fields the task needs. Replace identifying details with placeholders before the request leaves your server, keep any replacement map protected on your side, and never include passwords, API keys, or tokens in the prompt. Check provider terms and your own logs too: the model’s reply can contain sensitive information as well.

## Find what’s leaving your app

Look at the code that builds requests to the model. Does it pass a complete user object when the task only needs a support message? Does it attach a full error log when a short description would do?

Common places to inspect include:

- User records containing names, email addresses, and phone numbers.
- Support tickets with contact details embedded in free text.
- Logs containing authorization headers, tokens, or API keys.
- Application logs that save prompts or model replies.

The risk isn’t limited to an explicit “send customer data” feature. A debugging helper might attach an entire request to a prompt, including fields that aren’t visible in the app’s interface.

If you use a coding agent to inspect this flow, give it synthetic examples rather than real customer records. Ask it to report file paths and describe any exposed secret without printing the value.

For this kind of code review, you can [try the zcode agent harness free](https://zcode.z.ai/invite/ALWM9JUA) (our invite link). Whichever agent you use, inspect the actual request-building code and test what crosses the boundary yourself.

## Send the minimum the task needs

For each field, ask: what would the model do differently if it received this value?

If the task is to classify a support ticket as a billing, login, or delivery issue, the customer’s email address may not be needed. The model might only need the ticket text after identifying details have been removed. The application can keep the customer ID and use it locally to attach the result to the right record.

Choose fields explicitly rather than passing a whole database object. That way, a field added to the record later doesn’t automatically become part of the prompt.

[GDPR Article 5(1)(c)](https://gdpr-info.eu/art-5-gdpr/) describes data minimisation: personal data should be adequate, relevant, and limited to what is necessary for the purpose. Whether GDPR or another law applies to your app depends on the circumstances; this article isn’t legal advice. If you handle customer data for a client, check their requirements too.

Minimisation comes before redaction. Removing an unnecessary field is simpler than sending a disguised version of it.

Some tasks really do need context about a person. Decide whether a general description, such as “customer” or “account holder,” would work before including a detail that identifies them.

## Replace identifiers before the request

When the text itself contains details the model doesn’t need, replace them on your server before sending the request. For example:

```
Original, kept on your server:
Please reply to Maya at maya@example.com about the refund.

Sent to the model:
Please reply to [NAME_1] at [EMAIL_1] about the refund.
```

The address above is a fictional example. The placeholder lets the model refer to the detail without receiving its actual value.

If you need to restore a value in the final reply, keep the mapping on your server, scoped to the individual request or authorized user. Limit who can access it, keep it only as long as needed, and don’t include the map in prompts or logs.

Restore values only after checking that the recipient is authorized to see them. Treat the model’s reply as untrusted: accept only expected placeholders from the current request, and handle missing, altered, or unexpected placeholders without inserting someone else’s data. Log the redacted version, not the restored reply.

Pattern matching can help find email addresses and some phone numbers, but formats vary. It also won’t reliably catch names or other identifying details in free text. Test with synthetic examples and use a review or a more restrictive workflow when you can’t establish that the input is safe to send.

Pseudonymised text is not automatically anonymous. A ticket can still identify someone through its remaining details.

## Keep secrets out, including in errors

API keys, passwords, access tokens, and other credentials don’t belong in a prompt. Store credentials in the application’s protected configuration or a secrets manager, and give the model only the information needed for its task.

The [OWASP guidance on sensitive information disclosure](https://genai.owasp.org/llmrisk/llm022025-sensitive-information-disclosure/) identifies credentials and personal information among the data an LLM application may expose. It also recommends sanitization and limiting access to data sources.

Be careful with error reports. A request header, connection string, or copied stack trace can contain a credential. Build a safe diagnostic message from selected fields rather than forwarding raw logs.

If a secret has already been exposed, remove it from the flow and revoke or rotate it with the relevant provider. Don’t paste it into another prompt to ask whether it is safe.

Redaction is one part of the security review. For permissions, inputs, dependencies, and backups, use [secure your vibe-coded app before you ship](https://wurk.fun/blog/secure-your-vibe-coded-app-before-you-ship).

## Check retention and test the boundary

Read the terms for the **specific provider and API service** your app uses. Check what the provider says about request and response retention, logging, training, deletion, and available settings. Don’t assume a setting on one service applies to another. Update your privacy notice to describe your actual data handling, and get appropriate legal advice if needed.

On your side, avoid logging raw prompts or replies that may contain personal data. Review error tracking, debug logs, retries, and any stored conversations too. Where you need diagnostics, record limited metadata and protect access to it.

Ask your coding agent to make the change with synthetic test data:

```
Find every place this app sends data to an LLM.

Add a server-side step that sends only fields needed
for the task and replaces identifiers with placeholders.
Never send credentials, raw headers, or raw logs.

Keep any replacement map private and scoped to the
authorized request. Restore only expected placeholders
for an authorized recipient; keep restored data out of logs.
If redaction or validation fails, do not send the request.

Use synthetic data to test emails, phone numbers, names,
repeated values, secrets, and unexpected placeholders.
Test that raw values do not reach the provider or logs.
Report changes, test results, and detection gaps.
```

Review the tests and inspect the outbound request in a safe test environment. A passing test covers its examples; it doesn’t prove the redactor catches every possible identifier.

If you pay for a coding plan to run reviews like this, our referral link gives [10% off GLM coding plans](https://z.ai/subscribe?ic=R0K78RJKNW).

## A checklist before any prompt leaves your server

```
BEFORE SENDING A PROMPT

[ ] Only necessary fields are included
[ ] Identifiers are removed or replaced
[ ] Credentials and raw headers stay out
[ ] Placeholder maps are protected and scoped
[ ] Restoration checks the authorized recipient
[ ] Raw prompts and replies aren’t logged
[ ] Provider terms and privacy notice are checked
[ ] Synthetic tests cover failures and gaps
```

If this helped you protect customer data, a small WURK tip helps keep these guides coming. There’s [more on our blog](https://jackgross-five.vercel.app) too.
