NewStart 7-day trial
api pentest

An API pentest that finds the endpoints nobody wrote down.

Authorisation is where APIs fail, and it fails one endpoint at a time. It tests each one with accounts it controls, then shows you the request and the response that settled it.

api.acme.io
GET/v2/orders/{id}
POST/v2/orders/{id}/refund
PATCH/internal/users/{id}/role
DELETE/v1/legacy/export
GET/v2/statements
POST/v2/webhooks/test
31of 47 routes were missing from the spec
01 / How it works

Every endpoint, called as every account you give it.

What the scan reached, the accounts it called as, the patch it drafts and what reaches your team when it finishes.

Surface

It tests the endpoints, not the documentation.

The agent maps what the API actually answers to: from traffic, from the spec you upload and, with the repository connected, from the route definitions themselves. An endpoint written down nowhere is still in scope.

  • OpenAPI, WSDL or a Postman collection as context
  • Endpoints missing from your docs are tested too
  • The surface map shows what each run reached
Surface map
Surface mapreached this run
api.acme.io
GET/v2/orders
GET/{id}
POST/{id}/refund
GET/v2/accounts/{id}/statements
PATCH/internal/users/{id}/role
DELETE/v1/legacy/export
Scope · Documentation
Context for this scan
openapi.yaml184 KB
acme.postman_collection.json96 KB
architecture.png1.2 MB
3 of 5 documents · read-only to this scan's agents
Authorization

Same request. Different identity.

Give it two accounts and it replays each call as the other. When bob gets alice's order back, the finding carries the request, the response and the record that should never have crossed.

  • Signed in as the test accounts you add
  • One account per role, or per customer
  • Grey box for APIs you do not have the code for
Authenticated testing
Auth profiles · HTTP headers
Two tenants, replayed on every call
AL[email protected] Authorization: Bearer eyJhbGci…Q1
BO[email protected] Authorization: Bearer eyJhbGci…7x
criticalAny user can read another customer's orderWSTG-ATHZ-04
Observation
1GET /v2/orders/8842 HTTP/2
2Authorization: Bearer eyJhbGci…7x # bob
3
4HTTP/2 200
5{"id":8842,"customer":"[email protected]",
6 "total":"1,240.00","card_last4":"4417"}
Fix

The patch, on its own branch.

With the repository connected, a finding arrives with the change that closes it. Review it file by file, drop anything you do not want, and open it as a pull request.

  • Tied to the endpoint and parameter it fixes
  • A test for the endpoint, added alongside the fix
  • GitHub, GitLab or Bitbucket
Fixes and pull requests
Asset api.acme.ioEndpointGET /v2/orders/{id}Param id · pathAssigneeJR Jamie Reyes
FindingSuggested fixAIActivity3Notes
3 of 3 files included · +32 −1Branch fix/orders-owner-check · base main Open PR
src/routes/orders.ts+2−1
src/lib/authz.ts+6−0
src/routes/orders.test.tsnew+24−0
1414const order = await db.order.findFirst({
15− where: { id: req.params.id },
15+ where: { id: req.params.id, ownerId: user.id },
What comes back

Live while it runs. Findings when it ends.

Follow a run as it happens: which endpoints it has reached and what it is testing now. Findings are written up once the run ends, because something learned late in the run can change one found early. Then they go to the channel you pick, with the report generated from the same evidence.

  • Alerts in Slack, Teams or Discord when a run finds something
  • A ticket per finding in Jira, Linear or GitHub
  • A pentest report when the run ends
Alerts
api.acme.io38 of 56 endpoints tested
GET/v2/orders/{id} Tested
POST/v2/orders Tested
PATCH/v2/users/{id} Tested
GET/v2/invoicesTesting…
DELETE/v2/sessions/{id}Queued
Interopt#security · 18:40Run finished on api.acme.io: 1 critical, 2 high. Any user can read another customer's order.Open report →
02 / Coverage

What an API penetration test is looking for.

Most of an API's risk sits in who is allowed to call what, and it is rarely the only thing wrong.

01

Can one caller reach another's records?

Change an identifier and see whose record comes back. It reads the object afterwards, because a 200 is not proof.

02

Can a role call what it should not?

Routes the interface hides are still there to be invoked, and the platform exposes more than the client shows.

03

Can the client set what it was never given?

Role, tier or a verified flag posted on an update, and whether the value actually sticks.

04

Does the credential hold up?

Tokens that outlive a logout, refresh flows that hand back more than they were asked for.

05

What happens to a payload you did not expect?

Injection behind JSON bodies and query parameters, and what a malformed request gives back on the way out.

06

What does the response hand back?

An endpoint returning the whole record while the client renders three fields of it.

03 / Questions

Questions, answered.

ready when you are

Point it at your API.

A base URL and an account is enough to start. Connect the repository and the missing check comes back written.