CWE-201, Insertion of Sensitive Information Into Sent Data, describes code that transmits data to another actor when part of that data includes sensitive information the actor should not have. Any API, RPC service or message sender is exposed.
How it happens
The usual cause is over sharing by default. A handler loads a whole object, serialises all of it, and sends it. Fields meant for internal use or for the owner only travel along. A privacy setting gets checked on the profile page but not on the API endpoint.
MITRE's three examples fit that pattern:
- CVE-2023-27265: a collaboration platform did not honor a "show email address" setting in a response from an API endpoint.
- CVE-2023-32275: an RPC server for a VPN product returned an object containing heap addresses.
- CVE-2022-0708: a collaboration platform did not clear team emails in a response, allowing a leak of email addresses.
# Vulnerable: sends the whole record
@app.get("/users/<id>")
def get_user(id):
return jsonify(db.users.get(id).__dict__) # includes email, hash, internal flags
# Fixed: explicit public view that honors settings
@app.get("/users/<id>")
def get_user(id):
u = db.users.get(id)
out = {"id": u.id, "name": u.name}
if u.show_email:
out["email"] = u.email
return jsonify(out)
What an attacker gains
MITRE lists confidentiality impact: reading files or directories, memory, and application data. Leaked memory addresses are a quiet example, since they can make other attacks easier.
How to find it
MITRE says automated static analysis (SAST) can find some instances by modelling data flow. Beyond that, compare what each endpoint returns against what the client needs. Call the API as a low privilege user and as an anonymous user and diff the payloads. Look for objects that are returned wholesale.
Click through it at your own pace, or open it full screen.
How to fix it
The record lists no mitigations, so these are general steps.
- Build responses from an explicit allowlist of fields, not by serialising whole objects.
- Apply the same privacy settings and authorisation checks in every path that returns the data.
- Strip internal values such as pointers, internal identifiers and debug fields from external responses.
- Add tests that assert the exact set of fields in each response.
Quick check
Why is an allowlist of fields better than removing sensitive ones?
New fields added later are hidden by default. With a removal list, every new field leaks until someone remembers to add it to the list.