Safeguard
Application Security•

API Pen Test Cases for Mass Assignment and Rate Limits

Concrete test cases for OWASP API3 and API4 that you can run or hand to a tester: extra JSON fields, response over-exposure, per-endpoint limits and safe request volumes.

Safeguard Security Team
5 min read

AWS's penetration testing policy page, as it reads today, lists API Gateway among the services you may test without prior approval. It also lists "request flooding (such as login or API request flooding)" and any denial of service, including simulated, as prohibited. That pairing explains a common scoping problem. A tester has to prove your API lacks rate limits without flooding it.

Two items from the OWASP API Security Top 10 (2023) cause most of this friction: API3, Broken Object Property Level Authorization, which includes mass assignment, and API4, Unrestricted Resource Consumption. This post covers the properties on an object and the limits on a client. Object level checks (API1) are a separate test set.

What's affected

REST and GraphQL APIs that accept JSON bodies and return objects. The affected code paths are any create or update handler that binds client JSON straight onto a model, any endpoint that serializes a whole object, and any endpoint with no limit on rate, size or cost.

OWASP describes API3 as covering both excessive data exposure and mass assignment, and says it was called Mass Assignment in the 2019 edition. Its API4 examples include an SMS password reset flow that cost thousands of dollars within minutes and a GraphQL batching bypass that evaded per-request limits.

How to check if you're exposed

Run these against staging with the test accounts you set up for the tester. Replace the host and token.

Mass assignment, update path. Take a legitimate update and add fields the user should not control.

curl -s -X PATCH https://staging.example.com/api/v2/profile \
  -H "Authorization: Bearer $TOKEN_MEMBER" -H "Content-Type: application/json" \
  -d '{"display_name":"test","role":"admin","is_verified":true,"tenant_id":"other","plan":"enterprise"}'
curl -s https://staging.example.com/api/v2/profile -H "Authorization: Bearer $TOKEN_MEMBER"

If the second call shows any of the extra fields changed, you have mass assignment, tracked as CWE-915. OWASP's marketplace example works the same way: a host replays an approval request with an added total_stay_price field.

Mass assignment, create path. Repeat the test on POST with fields such as id, created_by, owner_id and status.

Excessive exposure. Request one object and compare every returned property against what your UI shows. Look for password hashes, internal flags, other users' emails and tokens. OWASP notes that APIs tend to expose endpoints that return all of an object's properties.

Rate limits, safely. Do not flood. Send a modest, bounded burst and look for a 429 or a change in behavior:

for i in $(seq 1 40); do
  curl -s -o /dev/null -w "%{http_code}\n" -X POST https://staging.example.com/api/v2/auth/login \
    -H "Content-Type: application/json" -d '{"email":"qa-user@example.com","password":"wrong"}'
done | sort | uniq -c

If all 40 return the same status, the login has no visible limit. Stop there. That is evidence, and a bigger volume adds risk without adding information.

Batching and cost. For GraphQL, send one request with an array of operations (a few, not thousands) and check whether a per-request limit counts each operation. Try a large page size parameter such as limit=100000 and watch the response size.

What to do now

  1. Use an allow list for writable fields. Bind only named properties on each route, per role. Avoid automatic binding of client input to internal objects, as OWASP recommends.
  2. Serialize explicitly. Select the properties to return. Do not call a generic to_json() on a model.
  3. Validate responses against a schema. A response schema catches a field added by accident.
  4. Set limits at three layers. Rate per client, per endpoint, with stricter rules on login, OTP and password reset. Maximum sizes for payloads, arrays, strings and uploads. Maximum page size and operations per request.
  5. Set spend limits or billing alerts on every paid third party, for example SMS and email providers. OWASP names this directly.
  6. Add both test sets to CI so a new field or endpoint cannot ship without them.

How to avoid this trap

  • Reuse one writable-field definition per resource in both the handler and the OpenAPI schema, so they cannot drift apart.
  • Rate limit on a stable identifier such as account and IP together. A limit that resets for every new IP is easy to bypass.
  • Make the tester's scope sheet say how much traffic is acceptable, so both sides know where the line is. Many cloud providers prohibit flooding.
  • Alert on a sudden rise in sends and spend, not just on traffic.

Why it matters

Both issues are cheap to exploit and easy to find, yet scanners tend to miss them because the requests look valid. A tester who thinks like a user with a few extra JSON fields will find them in an hour. A policy that forbids flooding means your own limits must be tested with small, careful bursts.

Treat the cases above as a baseline you can run yourself before every test. That leaves the vendor's time for harder problems such as business logic.

Try it yourself

Pick one write endpoint in staging and send the update test above with three extra fields. Record which fields changed. Then run the 40 request login loop and write down the status counts.

Click through it at your own pace, or open it full screen.

Quick check

Why not flood the login endpoint to prove there is no rate limit?

A bounded burst such as 40 requests already shows that no limit exists, and AWS's policy prohibits request flooding, including login or API request flooding.

Which API3 problem lets a user change a field they should not control?

Mass assignment, where the endpoint binds client input onto properties without checking whether the user may change each one.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.