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.
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.
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.
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.
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.
View the raw API response for a user profile.
Awaiting request...
passwordHash and ssn.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.
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.
// 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');
}
},
}),
},
],
});1.What is the primary cause of excessive data exposure in REST APIs?
2.Why does GraphQL make excessive data exposure worse than REST?
3.Which mitigation strategy is most effective for preventing excessive data exposure?