ASVS 5.0 V14.2.6 is a Level 3 requirement. The application must return only the minimum sensitive data its function needs, for example the last four digits of a card and not the whole number. When the full value is genuinely required, mask it in the interface until the user chooses to view it.
Why it matters
Data you never send cannot leak through a log, an XSS bug, a browser extension or a screenshot. Over sharing in API responses is common because serializers return whole database rows.
How to implement it
Use explicit response models, not raw records:
from pydantic import BaseModel
class CardOut(BaseModel):
brand: str
last4: str
exp_month: int
exp_year: int
# card_number and cvv are not fields, so they cannot be returned
function toPublicUser(u) {
return { id: u.id, name: u.name, emailMasked: u.email.replace(/^(.).*(@.*)$/, "$1***$2") };
}
For reveal on demand, put the full value behind a separate endpoint with its own authorization, rate limit and audit log, and require a recent authentication where the data justifies it.
How to test it
Call every endpoint that returns user data and read the raw JSON. Compare each field against the documented need. Search responses for patterns such as 13 to 19 digit numbers, full email addresses of other users and national identifiers.
Common mistakes
- Hiding fields in the UI while the API still returns them.
- Returning full objects "for the frontend to choose".
- Masking in the client only.
Quick check
Is hiding a field with CSS acceptable?
No. The data is already in the response and the page. Remove it at the server.