Why APIs need their own threat model
If you run a modern SaaS in the UK, the attack surface your customers actually interact with is not your marketing site — it is your API. Mobile clients, partner integrations, third-party dashboards, and increasingly AI agents all reach into the application through programmatic endpoints. The blast radius of a single authorisation bug on an authenticated API route is often greater than a cross-site scripting issue on a public page. And yet APIs receive less routine security attention, because they do not render visually to humans.
At YUPL we conduct CREST-certified penetration tests across dozens of UK SaaS companies each year. More than half of the critical findings we report are in API layers. This post walks through the current OWASP API Top 10, explains what each class of bug actually looks like in production, and gives you a test plan you can apply before you book a formal engagement.
1. Broken Object Level Authorisation (BOLA)
BOLA — sometimes called IDOR when you see it framed from the attacker's side — is by far the most common critical finding in our reports. The pattern is: an endpoint accepts an object ID in the URL or body, and the handler loads that object without checking whether the current user is authorised to see it. In a multi-tenant SaaS, this means tenant A can read, modify, or delete tenant B's records.
How to test: Create two accounts in different tenants. Log in as tenant A and capture a request that references a tenant-scoped object, for example GET /api/invoices/18425. Then replay the exact request authenticated as tenant B. If you get 200 instead of 403/404, you have BOLA. Repeat for every CRUD verb. Automated scanners are poor at this because they do not understand what "tenant" means in your data model.
2. Broken Authentication
The OWASP framing covers a broad range: missing rate limits on login, tokens that do not expire, refresh tokens that can be used after revocation, weak password policies, and crucially, inconsistent authentication across endpoint families. We frequently find a flagship API that enforces bearer tokens correctly alongside an older "internal" endpoint that trusts an X-User-ID header.
How to test: Enumerate every authentication path the API exposes — OAuth, cookie, JWT, API key, HMAC. Test each one in isolation for revocation, expiry, and rate limiting. Then check whether any endpoint accepts more than one mechanism. If so, check whether a lower-security mechanism can be used on a higher-sensitivity route.
3. Broken Object Property Level Authorisation
The cousin of BOLA. You correctly authorise whether a user can access an object, but you let them read or modify properties they should not see. Classic example: a PATCH /api/users/me endpoint that accepts the entire user model and lets the caller set role: "admin" or tenant_id: 4.
How to test: For every write endpoint, try submitting fields you did not legitimately receive. Payload enrichment is the pen tester's favourite move — fuzzing properties with sensitive names like is_admin, verified, price, parent_tenant_id. Most ORMs mass-assign by default, which is why Laravel's $fillable whitelist exists. Use it.
4. Unrestricted Resource Consumption
Can a single authenticated caller exhaust your CPU, database connections, email quota, or third-party API budget? This is the API equivalent of DoS. The failure mode is rarely about bringing the site down — it is about someone enumerating ten million records at the rate of a thousand per second, costing you hundreds of pounds in bandwidth and database load while they scrape a competitor's dataset.
How to test: Find paginated endpoints and try increasing limit beyond documented bounds. Find endpoints that trigger asynchronous work (email, webhook, PDF generation) and test what happens if you call them a thousand times a minute. Look for unbounded array inputs that drive database joins.
5. Broken Function Level Authorisation
Regular users should not be able to call administrative endpoints just by guessing their names. This sounds obvious but we routinely find that POST /api/users/123/impersonate is available to any authenticated user because the authorisation guard was applied at the router level to /admin/* only.
How to test: Get an authenticated non-admin token. Enumerate the API (Swagger docs, frontend source, directory brute force) and try every administrative verb you can find. Note especially endpoints whose authorisation is implemented in middleware or decorators, because these are the ones that slip through refactoring.
6. Unrestricted Access to Sensitive Business Flows
New in the 2023 edition, this category covers flows that are legal to call but should be rate-limited to real-world pace. Examples: booking all the seats for a popular event before anyone else can reach them, buying every unit of limited stock, registering thousands of free-tier accounts to launder traffic. The endpoints are not "vulnerable" in a classical sense — they just need to be treated as a business constraint, not just a technical one.
How to test: Identify flows with business asymmetry (one-per-customer, limited stock, signup bonuses). Attempt to run them in parallel from a single authenticated context. Attempt to run them across many newly-created accounts. Look for throttles scoped to IP, user, tenant, or device fingerprint.
7. Server Side Request Forgery (SSRF)
If your API lets a client pass a URL that the server then fetches — webhooks, image-upload-by-URL, OAuth callback validation, headless-browser screenshots — then SSRF is in your threat model. The attacker aims to make your server reach 169.254.169.254 (AWS metadata), localhost, or an internal service behind your firewall.
How to test: Supply URLs pointing at internal ranges and metadata endpoints. Supply DNS names that resolve to internal IPs. Supply redirect chains that start public and end internal. A correctly written SSRF guard resolves the hostname, checks the resolved IP against an allowlist, and then pins the connection to that IP to defeat DNS rebinding.
8. Security Misconfiguration
Default CORS policies that allow any origin. Error responses that leak stack traces. Verbose CORS headers. Missing HttpOnly or Secure on cookies. Production APIs that still expose /_debug or a Swagger UI without authentication. The OWASP category is a catch-all for "you deployed this without reading the hardening guide".
9. Improper Inventory Management
You have an API version v2 that is well-tested. Somewhere behind a load balancer, v1 is still accepting requests from a mobile app that hasn't been updated since 2022, and v1 never got the object-level authorisation fix that v2 received. This is the category that most surprises executives: "we didn't know that was still live".
How to test: Enumerate hosts, paths, and version prefixes. Pull archived Android APKs from apkpure, iOS IPA files from ipa-tool, and old JavaScript bundles from the Wayback Machine, and grep them for endpoint paths your current documentation does not mention.
10. Unsafe Consumption of APIs
Your API consumes data from a third party — a CRM webhook, an exchange rate feed, a shipping provider's tracking endpoint — and trusts that data implicitly. The attacker compromises or impersonates the upstream and feeds you malicious input. Internal APIs are often the "soft" layer: endpoints that would be heavily validated if exposed publicly, but which trust whatever the partner sends.
Tooling that actually works
The industry ships a parade of "API security" platforms. The truth is that two tools cover most of what you need to hunt the bugs above:
- Burp Suite Professional. The human's scalpel. Use it to intercept and replay requests, fuzz parameters with Intruder, and run Burp's scanner for low-hanging fruit.
- A tenant-aware test harness. Home-grown. Scripts that issue parallel requests from two test tenants and diff the responses. This is how you find BOLA at scale. Pytest +
httpxis plenty.
Everything else is a nice-to-have. We run nuclei templates against every API we test as a cheap first sweep, and we maintain a set of custom Python scripts that cover the things template-based scanners miss.
When to escalate to a formal pen test
Run the checks above yourself as a release gate. Book a formal CREST-certified penetration test before material milestones: enterprise procurement, ISO 27001 recertification, SOC 2 renewal, or a fundraise where technical due diligence is expected. If you are a UK business pricing this work for the first time, our UK pen test pricing guide breaks down what drives cost and what a typical engagement looks like.
If you want us to run this programme end-to-end — scoping, testing, reporting, and retest — the team at YUPL is available for quotes. We work with UK SaaS companies from Series A through to listed firms, and we write our reports so engineers can act on them without a decoder ring.
About the author. Spencer Schotel is the CTO of YUPL, a CREST-certified UK agency specialising in secure Laravel development and application penetration testing. He has led security engagements for UK fintech, e-commerce, and public-sector platforms.