Skip to content
bughunter.pro
/Request an audit

API security audit, where your data actually lives.

An API security audit verifies that every REST, JSON or GraphQL endpoint exposes only what it should, and only to whoever should reach it. With no interface to hide behind, an API enforces exactly the rules somebody wrote for it. The whole question is whether those rules were ever actually written.

01The problem

Access control does not live in the button.

In a conventional application the interface guides the user. It hides forbidden actions, greys out buttons, never renders the fields reserved for administrators. Plenty of teams quietly conclude, without ever saying it out loud, that a user can only do what the interface offers.

An API has no interface. It has routes, and anyone can call them directly, with whatever parameters they like, in whatever order they like. If the check "is this user allowed to read this specific object?" was not written on the server for that route, it does not exist.

This is the most common and the most serious flaw I find on APIs. It needs no sophisticated tooling: changing one identifier in an otherwise legitimate request is enough. It produces no error in your logs, because as far as the server is concerned, everything went fine.

02Coverage

What I test.

REST, JSON, GraphQL, webhooks, OAuth and OIDC, WebSockets. These are the families covered every time.

  • Object level authorization (BOLA, IDOR): reaching another account's resources by changing an identifier.
  • Function level authorization (BFLA): calling an admin route with a standard account.
  • Mass assignment: slipping an unexpected field into a request body, such as a role or a payment status.
  • Excessive data exposure: a response returning the full object when the interface only displays three fields of it.
  • Authentication and tokens: JWT signature validation, accepted algorithms, expiry, revocation, refresh flows.
  • GraphQL specifics: open introspection, expensive nested queries, controls placed on the route instead of the resolver, aliasing to defeat limits.
  • Server-side injection: SQL and NoSQL through filters, SSRF on parameters that trigger an outbound call.
  • Rate and logic abuse: missing limits on sensitive routes, replayable operations, account enumeration.
03Process

How an engagement runs.

01

Scoping and access

We list the APIs in play, the environments, and the roles to cover. Ideally you provide an OpenAPI specification or a GraphQL schema, plus a set of distinct accounts: at minimum two accounts at the same level, to test horizontal access, and one account at each privilege level.

02

Route mapping

A full inventory of endpoints, accepted methods, parameters and response shapes. This step routinely surfaces forgotten routes: old versions still online, internal endpoints reachable from outside, debug routes left active.

03

Authorization matrix

The core of the work. For every sensitive route I replay the same request with each role and with object identifiers belonging to other accounts. This matrix is what separates a serious API audit from a scanner pass: it is mechanical, exhaustive, and it finds things.

04

Data manipulation

Extra fields injected into request bodies, altered types, boundary values, unexpected nested structures. The goal is to find what the server accepts when it should not.

05

Report, debrief, retest

A report prioritized by real severity, with the exact request that demonstrates each flaw, what an attacker would gain from it, and the fix to apply. A debrief with the team, then a retest of every fix, included.

04Examples

What this looks like in practice.

Real findings, reported and fixed. Client identities and perimeters are never disclosed.

BOLA Reading any customer's data by incrementing an identifier in an otherwise legitimate request.
Critical
Mass assignment Standard account promoted to administrator through an unfiltered field at sign-up.
Critical
Data exposure API response returning personal fields the interface never displayed.
High
GraphQL Access control enforced on the root query but missing from nested resolvers, bypassable through a relation.
High
Billing bypass Full use of a paid API without ever triggering the payment.
High
05Budget

What it costs.

Quoted per engagement, like all of them. On an API, two variables dominate everything else.

The number of sensitive endpoints first: not the total route count, but the ones that handle data or rights. Then the number of roles. These two multiply: the authorization matrix to verify is the product of both. An API with fifteen meaningful routes and two roles goes quickly. At a hundred routes and six roles the workload is in another league.

On top of that, GraphQL demands its own approach, and inbound webhooks or third-party integrations each add surface. Providing an up-to-date OpenAPI specification cuts the mapping time noticeably, and therefore the quote.

06FAQ

Common questions.

Do I need to provide API documentation?

Not mandatory, but an OpenAPI specification or a GraphQL schema speeds up coverage considerably and lets me test endpoints no client consumes yet. Failing that, I map the API by observing the real traffic from your client applications.

My API is protected by a key, is that enough?

No. A key answers the question of who is calling, never the question of whether they are allowed to reach this specific object. The vast majority of serious API flaws I find are object level authorization failures, not authentication failures.

Is GraphQL riskier than REST?

Not inherently, but it moves the risk. Introspection often exposes the entire schema, nested queries let you reach objects through paths nobody anticipated, and a single deep query can cost the server dearly. Controls have to sit at the resolver, not on the route.

Do you test webhooks and third-party integrations too?

Yes, when they are in scope. Inbound webhooks are a frequently forgotten entry point: unverified signatures, replayable requests, or handlers that trust the payload they receive. OAuth and OIDC are covered as well.

What if the API is in production?

That is the most common case and it is not a problem. Destructive tests and load tests are excluded by default. On write endpoints I work against resources created for the occasion rather than your real data.

08Contact

Get your API audited.

Tell me how many sensitive routes and how many roles you have, and whether you have an OpenAPI specification or a GraphQL schema. I come back with a scope and a quote. First conversation carries no commitment, full confidentiality.