Login
ChallengesLearn
Scoreboard
Teams
Profile

Preferences

Truesapiens

LearnAPI SecurityExcessive Data Exposure
API Security·Lesson 5 of 11

Excessive Data Exposure

OWASP API #3. The API returns the full database row — password hash, internal notes, PII — and trusts the client to only render what it needs. Over-fetching in REST and the GraphQL query depth problem.

Intermediate12 min
APIExposureData Leak
Loading lesson…
PreviousBroken AuthenticationNextAPI Mass Assignment

© 2026 Truesapiens.

Terms of ServicePrivacy PolicyCookie Policy

The API returns the full database row including sensitive fields like password hashes, internal notes, PII, and audit columns — and trusts the client to only render what it needs. This is OWASP API Security Top 10 #3: Excessive Data Exposure.

What you'll be able to do
  • Identify excessive data exposure in API responses.
  • Understand why CRUD frameworks and GraphQL make this vulnerability common.
  • Apply response filtering, DTOs, and field-level middleware to prevent leaks.
Key terms
DTO (Data Transfer Object)
An object that defines exactly which fields should be returned by an API endpoint, decoupling the response shape from the internal model.
Response projection
Limiting which fields are included in an API response, either through server-side selection or client-side query parameters.
GraphQL field-level middleware
Middleware that runs per-field in GraphQL resolvers, allowing fine-grained access control and field filtering based on user permissions.
Auto-serialisation
The automatic conversion of database models to JSON by frameworks such as Django REST Framework or Spring Boot, which often includes all columns by default.
What is it?

The full row problem

Excessive data exposure occurs when an API endpoint returns more data than the client needs. The most common cause is auto-serialisation: a framework takes the database model and converts every column to JSON without filtering. The server trusts the client to hide sensitive fields in the UI, but the data is already visible in the network response.

This pattern is endemic in CRUD frameworks. Django REST Framework's ModelSerializer, Spring Boot's Jackson auto-serialisation, and Ruby on Rails' to_json all default to including every attribute on the model. The developer must explicitly opt out of fields — a step that is easily forgotten during rapid development.

Excessive data exposure flow
Mini Map
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Try it

Profile viewer

Toggle between vulnerable mode — where the API returns the full database row including sensitive fields — and safe mode, where a DTO strips everything except the display fields.

Profile Viewerprod
Aalice
GET /api/users/42

Profile viewer

View the raw API response for a user profile.

API response
Click “View profile” to load the API response.
Response headers

Awaiting request...

Tip: Toggle between vulnerable and safe mode. In vulnerable mode, the API returns the full database row including sensitive fields like passwordHash and ssn.
Real-world relevance

Facebook / Instagram passwords 2019

In 2019, Facebook disclosed that millions of Instagram passwords were stored in plaintext and exposed via the GraphQL API. The account data endpoint returned a password field in the response — the field was never meant to be rendered in the client, but the GraphQL schema included it and no field-level middleware blocked it. A determined attacker could query the full schema definition, discover the password field, and retrieve it for any account.

GraphQL exacerbates excessive data exposure because the client specifies exactly which fields to return. If the schema exposes a sensitive field like passwordHash or internalNotes, any client can request it via a deep query — even if the main application never asks for it. The server must treat the GraphQL schema as a public attack surface and apply field-level authorisation to every resolver.

Mitigation

Response filtering, DTOs, and field-level middleware

The fix has three layers. First, never auto-serialise models to JSON. Define a DTO per endpoint that explicitly lists the allowed response fields. Second, use response projection — frameworks like Spring Boot and Django REST Framework support annotating which fields to include at the serializer level. Third, for GraphQL, apply field-level middleware that checks permissions before every resolver call.

javascriptsafe
// VULNERABLE — Django REST Framework ModelSerializer
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'  # includes password_hash, ssn, internal_notes

// VULNERABLE — Spring Boot entity returned directly
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
    return userRepository.findById(id).orElseThrow();
    // Jackson serialises every field including passwordHash
}

// SAFE — explicit DTO with only display fields
class UserProfileDTO(
    val name: String,
    val email: String,
    val avatar: String,
)

@GetMapping("/users/{id}")
fun getUser(@PathVariable id: Long): UserProfileDTO {
    val user = userRepository.findById(id).orElseThrow()
    return UserProfileDTO(
        name = user.name,
        email = user.email,
        avatar = user.avatar,
    )
    // passwordHash, ssn, notes are never serialised
}

// SAFE — GraphQL field-level middleware (Apollo Server)
const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    {
      requestDidStart: () => ({
        fieldDidStart: ({ source, args, contextValue }) => {
          if (
            source.fieldName === 'passwordHash' &&
            contextValue.user.role !== 'admin'
          ) {
            throw new GraphQLError('Forbidden');
          }
        },
      }),
    },
  ],
});
Further reading
  • OWASP API Security #3 — Excessive Data Exposure(OWASP)
  • Instagram passwords exposed in GraphQL API (Facebook 2019)(Wired)
  • GraphQL field-level authorisation patterns(Apollo Docs)
Key takeaways

What to remember

  • Auto-serialising database models to JSON is the root cause — the entire row is exposed in the response.
  • DTOs per endpoint are the simplest defence: explicitly list every field the client should see.
  • GraphQL makes the problem worse because the schema is introspectable and every field is requestable — apply field-level middleware.
  • The Facebook / Instagram incident (2019) is the landmark case: a password field existed in the GraphQL schema and was returned to any client that asked for it.

Knowledge check

0/3 answered · 0 correct
  1. 1.What is the primary cause of excessive data exposure in REST APIs?

  2. 2.Why does GraphQL make excessive data exposure worse than REST?

  3. 3.Which mitigation strategy is most effective for preventing excessive data exposure?