---
title: "Mask sensitive values until people ask to · Agent Wranglers"
url: https://agentwranglers.se/playbook/app-ui/data-views/mask-sensitive-values
id: APP-75
level: Recommended
updated: 2026-10-22
build: a2a6bdfed830
tokens: 1019
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Mask sensitive values until people ask to see them

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Data views](https://agentwranglers.se/playbook/app-ui/data-views.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: APP-75
- Level: Recommended
- Chapter: [Data views](https://agentwranglers.se/playbook/app-ui/data-views.md)
- Rule: Show bank account numbers, government ID numbers and stored secrets masked, such as the last 4 characters. Send the full value only when a person with the permission presses Show, and log each request.
- Check: Load a customer list and a detail page as a support user. The responses hold only the last 4 characters of each masked field. Pressing Show returns the full value and adds 1 audit entry. A user without the permission gets a 403.
- How: The server sends only the masked form in lists and detail views, so the full value never sits in the page or its cached data. A Show button calls a separate endpoint that checks the permission, writes who asked and when to the audit log, and returns the value. Hide it again when the person leaves the screen. Replies carry nothing else the screen does not show, as [return only the fields needed](https://agentwranglers.se/playbook/application-security/access-control/only-needed-fields.md) says. Card numbers never reach your servers at all under [keep card numbers off your servers](https://agentwranglers.se/playbook/payments/card-security-and-sca/pci-saq-a-integration.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Python example

```python
def masked(value: str) -> str:
    return "•••• " + value[-4:]

@app.get("/customers/<customer_id>")
def customer_detail(customer_id):
    customer = customers.get(current_user().account_id, customer_id)
    return {"name": customer.name, "bank_account": masked(customer.bank_account)}

@app.post("/customers/<customer_id>/bank-account/reveal")
def reveal_bank_account(customer_id):
    require_permission(current_user(), "customers.reveal_bank_account")
    customer = customers.get(current_user().account_id, customer_id)
    audit.write(actor=current_user().id, action="reveal_bank_account", target=customer.id)
    return {"bank_account": customer.bank_account}
```

### TypeScript example

```ts
export async function revealBankAccount(customerId: string, field: HTMLElement) {
  const response = await fetch(`/customers/${customerId}/bank-account/reveal`, { method: 'POST' });
  if (!response.ok) return showStatus('You do not have access to the full number.');
  const { bank_account } = await response.json();
  field.textContent = bank_account;
  addEventListener('pagehide', () => { field.textContent = ''; }, { once: true });
}
```

## Sources

- [OWASP ASVS 5.0 V14 Data Protection, 14.2.6 on masking in the user interface](https://github.com/OWASP/ASVS/blob/master/5.0/en/0x23-V14-Data-Protection.md)

## Related rules

- APS-22 [Return only the fields needed](https://agentwranglers.se/playbook/application-security/access-control/only-needed-fields.md) in Application security
- PAY-1 [Choose a checkout that keeps you on SAQ A](https://agentwranglers.se/playbook/payments/card-security-and-sca/pci-saq-a-integration.md) in Payments and billing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/app-ui/data-views/mask-sensitive-values">Agent Wranglers web app interface playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Say why a control is unavailable](https://agentwranglers.se/playbook/app-ui/data-views/disabled-with-reason.md)
- [Data views](https://agentwranglers.se/playbook/app-ui/data-views.md)
