7 Security Risks in Legacy GraphQL Java APIs (And How to Fix Them)

⚠️ Warning: These vulnerabilities can expose sensitive data or crash your server.
Fix them immediately if you’re using GraphQL Java Kickstart.

GraphQL Java APIs face unique security risks due to query flexibility.
Unlike REST, a single malicious query can expose sensitive data or crash your server.
This guide shows exactly how to fix the 7 most critical vulnerabilities.

🔒 Free: GraphQL Security Configuration Templates

Download ready-to-use Java classes for depth limiting, rate limiting, and authorization (copy-paste ready)



1. Query Depth Attacks

Problem: Deeply nested queries can crash your server.

Fix: Limit query depth to 10 levels.


@Component
public class QueryDepthInstrumentation implements Instrumentation {
    private final int maxDepth = 10;
    
    @Override
    public InstrumentationContext<ExecutionResult> beginExecution(
        InstrumentationExecutionParameters parameters) {
        
        QueryTraverser traverser = QueryTraverser.newQueryTraverser()
            .schema(parameters.getSchema())
            .document(parameters.getQuery())
            .build();
            
        int depth = traverser.reducePreOrder((env, acc) -> 
            Math.max(acc, env.getParentEnvironment() == null ? 1 : acc + 1), 0);
            
        if (depth > maxDepth) {
            throw new ValidationException("Query depth exceeds: " + maxDepth);
        }
        return super.beginExecution(parameters);
    }
}

2. Introspection Abuse

Problem: Attackers can see your entire schema.

Fix: Disable introspection in production.


@Configuration
@Profile("production")
public class ProductionGraphQLConfig {
    @Bean
    public GraphQLSchema graphQLSchema() {
        return GraphQLSchema.newSchema()
            .query(queryType)
            .mutation(mutationType)
            .fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY)
            .build();
    }
}

3. SQL Injection

Problem: User input in queries → database breach.

Fix: Use parameterized queries + validation.


// BAD (vulnerable)
String sql = "SELECT * FROM products WHERE name LIKE '%" + searchTerm + "%'";

// GOOD (safe)
String sql = "SELECT * FROM products WHERE name LIKE ?";
return jdbcTemplate.query(sql, new Object[]{"%" + searchTerm + "%"}, mapper);

4. Field-Level Authorization Bypass

Problem: Users see fields they shouldn’t access.

Fix: Check permissions in every resolver.


@SchemaMapping
public String email(User user, Authentication auth) {
    if (!authService.canViewEmail(auth.getName(), user.getId())) {
        throw new AccessDeniedException("Insufficient permissions");
    }
    return user.getEmail();
}

5. Batching Attacks

Problem: 100 queries in one batch → server crash.

Fix: Limit batch size to 10.


@Component
public class BatchLimitingInstrumentation implements Instrumentation {
    private final int maxBatchSize = 10;
    
    @Override
    public InstrumentationContext<ExecutionResult> beginExecution(...) {
        List<ExecutionInput> batch = parameters.getExecutionInput().getBatch();
        if (batch != null && batch.size() > maxBatchSize) {
            throw new ValidationException("Batch size exceeds: " + maxBatchSize);
        }
        return super.beginExecution(parameters);
    }
}

6. Missing Input Validation

Problem: Malicious arguments → data leaks.

Fix: Validate all inputs with @Valid.


@SchemaMapping
public Product createProduct(@Valid ProductInput input) {
    Set<ConstraintViolation<ProductInput>> violations = validator.validate(input);
    if (!violations.isEmpty()) {
        throw new ValidationException("Validation failed");
    }
    return productService.createProduct(input);
}

7. Repeated Queries (DoS)

Problem: Same heavy query → server overload.

Fix: Implement rate limiting.


@Component
public class GraphQLRateLimiter {
    public boolean tryConsume(String userId, ExecutionInput input) {
        int queryCost = calculateQueryCost(input);
        return rateLimiter.tryAcquire("rate_limit:" + userId, queryCost);
    }
}

Security Checklist

  • ☐ Set maximum query depth (recommended: 10)
  • ☐ Disable introspection in production
  • ☐ Implement field-level authorization
  • ☐ Use parameterized queries
  • ☐ Validate all input arguments
  • ☐ Limit batch size to 10
  • ☐ Implement rate limiting
  • ☐ Monitor authentication failures

Recommended Tools

Test your API security with these tools:

  • Apollo Studio — Schema validation and security scanning
  • Snyk — Dependency vulnerability scanning