Make a field policy before testing

For each object, name the owner and each field class. A payout response may include amount and status for the customer, bank reference for a partner, and fraud notes for staff. Test normal JSON, expanded relations, CSV export, and error responses against the same field policy. If a field is intentionally public in one context, document that context so the tester does not call a planned disclosure a flaw.

For updates, send hidden fields even when the UI never sends them. An API may bind incoming JSON directly to a database model. Test a normal allowed update and then add one forbidden property. A safe implementation can reject the request or ignore the forbidden property under a clear contract. Read back the stored row to prove that the forbidden property stayed unchanged.

Test cases and proof

Use test accounts and test data
CaseExpected resultProof to keep
Customer requests internal risk fieldOmit itRaw JSON response
Customer submits settlement statusReject or ignore itStored record
Partner asks for nested customer dataApply field rules inside nested objectResponse and access log

Synthetic example

A customer can read their payout record, but the record also contains an internal riskDecision field. Test whether field selection, nested queries, and a full JSON response expose it. For writes, send riskDecision in a normal payout update and confirm that the stored value does not change.

Choose a write policy

Rejecting a payload with staff-only fields tells the client it used an unsupported input. Ignoring those fields can preserve older clients, but it needs a precise allowlist and a test that the stored row stayed unchanged. Pick one policy for each endpoint and document it. The read side needs its own allowlist. A serializer that removes risk notes from a normal response will not automatically remove them from an export or nested object. Test every output shape that shares the same object.

Related reading

Why these checks matter

OWASP API3 groups excessive data exposure and mass assignment under object property authorization. That is why the test checks both response fields and fields sent in a write. The broader OWASP authorization guide adds a deny-by-default rule: a newly added property should not become public just because no one wrote a block for it.

Keep one stable payout fixture

Synthetic payout P-101 belongs to customer A. Its label is “October invoice,” amount is 500,000 kobo, status is pending, and internal riskDecision is review. A may change the label only. PATCH the label to “Invoice 101” and include riskDecision=allow, status=paid, and an unknown override flag. Under a reject-whole-request contract, no field changes. Under an ignore-forbidden-fields contract, only the label changes. Choose the contract first and read all four stored values after the request.

Now request the same payout as A through normal JSON, fields selection, a nested recipient, and export. Mark riskDecision with a unique fake value so a leaked field is easy to find. An allowed object ID does not grant all fields. Use a separate staff fixture for roles that may see risk data; do not change the expected customer rule halfway through the test.

Test defaults after a schema change

Add a synthetic internal property riskReason to the database model in staging. Run the same serializer and update tests without adding it to the customer allowlist. Expect the new property to remain unreadable and unwritable. Test an error that includes submitted field values too; a validation failure can echo a private field.

Keep response and write allowlists separate. Read filters protect output; they do not stop database assignment. An input DTO or explicit field map should select only writable values before update. Record the endpoint, role, field name, expected rule, and before/after value. OWASP API3 covers this read/write risk; the payout fixture makes the rule testable.

Source