ASVS 5.0 V14.1.1 is a Level 2 requirement. You must identify every piece of sensitive data your application creates or processes and place it in a protection level. The requirement specifically names data that is merely encoded, such as Base64 strings or the readable payload inside a JWT, because encoded is not protected.
Every other data protection requirement depends on this inventory.
Why it matters
You cannot protect what you have not found. Teams usually know about passwords and card numbers. They forget the session identifier in a log line, the email address inside an analytics event, the national ID in a support attachment, or the user id and role claims in a token anyone can decode.
Protection levels also have to reflect the rules you operate under, such as privacy laws and industry standards. Which rules apply is a legal question for your organization. The engineering job is to make the data map precise enough to answer it.
How to implement it
Start with a data inventory kept in the repository, next to the code, so it changes with the code.
# data-classification.yaml
levels:
public: { retention: indefinite }
internal: { retention: 3y }
confidential: { retention: 1y, encrypt_at_rest: true, log: never }
restricted: { retention: 90d, encrypt_at_rest: true, log: never, mask_in_ui: true }
data:
- name: email_address
level: confidential
stores: [users.email, analytics.events]
- name: jwt_payload
level: confidential
note: "Base64url encoded, readable by any holder. Contains sub and role."
- name: card_number
level: restricted
stores: [none, tokenized at provider]
Then do the work of finding data:
- Walk the schema. List columns and mark each.
- Walk the API. For each response field, record the level.
- Walk logs, traces, analytics events and error reports.
- Decode what looks opaque. Paste a token or a blob into a decoder and see what a stranger would see.
- Review third party calls, because data leaves through SDKs.
Keep the file small enough that people actually update it. A pull request template question such as "does this change add or move sensitive data?" keeps it alive.
How to test it
- Pick five random database columns and five random API fields. Each should appear in the inventory.
- Decode every token format you issue. The classification must mention what is inside.
- Grep a day of logs for patterns such as email addresses or long numeric strings. Anything found that is classified as never loggable is a defect.
Common mistakes
- Treating encoding as protection. Base64 and the JWT body are readable by anyone.
- Classifying tables but not fields, so a mixed table gets the lowest level.
- A one time spreadsheet exercise that nobody maintains.
- Ignoring derived data such as search indexes and caches.
Quick check
Is a signed JWT confidential?
Signing protects integrity, not confidentiality. The payload is readable, so anything sensitive in it should be classified and probably moved out.