Login
ChallengesLearn
Scoreboard
Teams
SPNZ

LearnAPI SecurityAPI Automated Security Testing
API Security·Lesson 8 of 11

API Automated Security Testing

Contract testing, schema fuzzing, OpenAPI/Swagger-based scanning, GraphQL introspection + automated query generation, and CI pipeline integration. How to find API vulnerabilities before they ship.

Intermediate14 min
APITestingAutomation
Loading lesson…
PreviousAPI Rate Limiting & AbuseNextAPI Security Hardening

© 2026 SPNZ.

Terms of ServicePrivacy PolicyCookie Policy

Manual security testing does not scale. As APIs grow from a handful of endpoints to hundreds, automated security testing becomes the only practical way to catch regressions, misconfigurations, and logic flaws before they reach production. This lesson covers contract testing, fuzzing, GraphQL-specific analysis, and CI pipeline integration.

What you'll be able to do
  • Explain how contract testing enforces API specifications at build time.
  • Describe fuzzing techniques for sending unexpected payloads to API endpoints.
  • Analyse GraphQL introspection queries to discover hidden schema features.
  • Integrate automated security tests into a CI/CD pipeline.
Key terms
Contract testing
A testing approach that validates API responses against a formal specification (e.g. OpenAPI/Swagger). Ensures the implementation matches the documented schema, including required fields, data types, and response codes.
Fuzzing
A technique that sends unexpected, malformed, or boundary-value inputs to an API to trigger edge-case failures. Includes type confusion (sending a string where a number is expected), missing fields, and oversized payloads.
GraphQL introspection
A built-in GraphQL feature that exposes the full schema via the __schema query. In production, introspection should be disabled to prevent attackers from mapping every type, field, and resolver in the API.
Static Application Security Testing (SAST)
Security testing that analyses source code without executing it. For APIs, SAST tools check for hardcoded secrets, missing authentication decorators, and insecure deserialisation patterns.
What is it?

Automated security testing for APIs

Contract testing is the first line of defence. Given an OpenAPI or Swagger specification, automated tools validate that every endpoint returns the correct status codes, response shapes, and content types. A mismatch between spec and implementation — for example, a field documented as string that returns number, or a documented 404 handler that never actually fires — signals a bug that might also be a security vulnerability.

Fuzzing goes a step further by sending inputs the spec never intended. A fuzzer might send a JSON array where a string is expected, omit a required field, set a numeric field to a negative number, or send a 10-megabyte payload to a name field. The goal is to find deserialisation errors, buffer overflows, SQL injection points, and denial-of-service vectors that would never appear in normal usage.

GraphQL APIs require specialised analysis. The introspection system (via the __schema query) exposes every type, field, argument, and resolver in the API. Automated tools can extract the full schema, analyse it for common weaknesses (missing authentication on mutation types, excessive nesting depth, unused fields that leak internal data), and generate a risk report.

Automated security testing pipeline
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

API security scan dashboard

Run an automated security scan against a simulated API. Watch each stage execute and review the final vulnerability report.

api-security-scanstaging
idle
api-security-scan · CI pipeline dashboard

Automated API Security Scan

Run a full security scan against the API surface.

Progress0/6 stages
Pipeline stages
OpenAPI validation1/6
Endpoint discovery2/6
Parameter fuzzing3/6
Auth testing4/6
GraphQL analysis5/6
Report generation6/6
Findings

Run a scan to see security findings.

Real-world relevance

Uber 2016 — security testing found auth tokens in unexpected responses

In 2016, Uber's security team ran automated contract and fuzz tests against their internal API suite. The tests discovered that several API endpoints returned authentication tokens in response to unauthenticated requests — a bug that had been present for months without detection. Because the endpoints were designed for authenticated use, the developers had never tested them without a valid session.

The root cause was an implicit trust relationship: the API controller assumed that if a request reached it, the request had already passed authentication middleware. An endpoint reorganisation had accidentally placed some routes before the authentication middleware in the route table, making them publicly accessible. Automated fuzzing caught the issue because it sent requests without session cookies to every endpoint — including the ones the developers assumed were “internal only”.

Uber subsequently integrated automated API security scanning into their CI pipeline, running contract tests, fuzz tests, and GraphQL introspection analysis on every pull request. The bug was fixed before any external attacker discovered it. This case demonstrates why automated testing is not just about finding bugs — it is about finding the bugs that manual testing would never think to look for.

Mitigation

Building a CI-integrated API security test suite

An effective automated security testing pipeline combines three layers: contract validation, fuzzing, and GraphQL-specific analysis. Contract tests run first and fail fast if the implementation diverges from the spec. Fuzzing runs against every endpoint with a combinatorially generated set of malformed inputs. GraphQL analysis extracts the schema and checks for dangerous configurations.

typescriptsafe
// Contract test example (Vitest + supertest)
import { describe, it, expect } from 'vitest';
import request from 'supertest';
import spec from './openapi.json' assert { type: 'json' };

describe('API contract tests', () => {
  it('GET /api/users returns 200 with user array', async () => {
    const res = await request(app).get('/api/users');
    expect(res.status).toBe(200);
    expect(Array.isArray(res.body)).toBe(true);
    expect(res.body[0]).toHaveProperty('id');
    expect(typeof res.body[0].id).toBe('number');
  });

  it('GET /api/users/:id returns 404 for unknown user', async () => {
    const res = await request(app).get('/api/users/999999');
    expect(res.status).toBe(404);
    expect(res.body).toHaveProperty('error');
  });
});

// Fuzz test — send unexpected types
describe('API fuzz tests', () => {
  const fuzzPayloads = [
    { name: null },
    { name: 12345 },
    { name: { '$ref': '#/definitions/User' } },
    { name: 'A'.repeat(100_000) },
    {},
  ];

  it.each(fuzzPayloads)('POST /api/users with %j', async (body) => {
    const res = await request(app)
      .post('/api/users')
      .send(body)
      .set('Content-Type', 'application/json');
    // Should never return 500
    expect(res.status).not.toBe(500);
  });
});

// GraphQL introspection check
describe('GraphQL security', () => {
  it('introspection is disabled in production', async () => {
    const res = await request(app)
      .post('/graphql')
      .send({ query: '{ __schema { types { name } } }' });
    // In production, introspection should return 400 or empty
    expect(res.body.data?.__schema).toBeUndefined();
  });

  it('query depth is limited to 5', async () => {
    const deepQuery = '{ a { b { c { d { e { id } } } } } }';
    const res = await request(app)
      .post('/graphql')
      .send({ query: deepQuery });
    expect(res.status).toBe(400);
  });
});
Further reading
  • OWASP API Security Testing Guide(OWASP)
  • Uber API security testing blog (2016)(Uber Engineering)
  • OpenAPI specification validation tools(Swagger)
  • GraphQL security testing cheatsheet(OWASP Cheat Sheet Series)
Key takeaways

What to remember

  • Contract tests validate that the API implementation matches the OpenAPI spec — a mismatch is often a security bug in disguise.
  • Fuzzing finds bugs that manual testing misses: type confusion, missing field handling, and denial-of-service via oversized payloads.
  • GraphQL introspection should be disabled in production; automated tools can detect when it is enabled and extract the full schema.
  • CI integration ensures security tests run on every pull request, not just during dedicated security reviews.
  • The Uber 2016 case proves that automated testing catches bugs caused by implicit trust assumptions — endpoints that were “internal only” but publicly accessible.

Knowledge check

0/3 answered · 0 correct
  1. 1.What is the primary goal of contract testing for APIs?

  2. 2.What did Uber's automated security testing discover in 2016?

  3. 3.Why is GraphQL introspection considered a security risk in production?