Mert Özen Further With Every Line
Security API Security (OWASP API Top 10) — #11

OWASP API Security Top 10: What Changed from 2019 to 2023 and Reading Old Reports in Today's Terms

Mert Özen Nov 8, 2026 11 min 4 views
OWASP API Security Top 10: What Changed from 2019 to 2023 and Reading Old Reports in Today's Terms

In the 2023 edition Excessive Data Exposure and Mass Assignment merged into BOPLA, API2, API4 and API9 were renamed, Injection and Logging left the list, and sensitive business flows, SSRF and unsafe consumption were added; so old findings are mapped by meaning, not by number. A mapping table, a small tool that translates old reports and shows unassessed categories, and what we'll do when a new edition arrives.

Version note: This post follows the 2019 and 2023 editions of the OWASP (Open Worldwide Application Security Project) API (Application Programming Interface) Security Top 10; as of November 2026 no new edition has been announced. The sample tool was built and run with .NET 10.

Guess First

A 2022 pentest report lands on your desk. It contains findings titled API6 (Mass Assignment) and API8 (Injection). Someone on the team labels them with the same numbers from the 2023 list and enters them into the tracking system: API6 is now "Unrestricted Access to Sensitive Business Flows", and API8 is "Security Misconfiguration". Both findings are in the wrong category and nobody notices, because the numbers look familiar.

There's a silent problem too: since the report was prepared against the 2019 list, SSRF (Server Side Request Forgery), sensitive business flows and unsafe consumption of third-party APIs were never assessed. No findings under those headings doesn't mean "clean", it means "not looked at".

This is the last post of the series and a release post: we talk about what changed in the list from 2019 to 2023, how to translate old reports and documents into today's categories, and how we'll update this series when the next edition arrives. We covered the changes between editions of the Web Top 10 in two separate posts of the Web Security (OWASP Top 10) series; here we apply the same habit to the API list.

The Two Lists Side by Side

The first API Security Top 10 was published in 2019, and the second edition came four years later, in 2023. According to OWASP's release notes three items stayed the same, three were renamed, two merged, two left the list and three new items were added:

20192023Change
API1 (Broken Object Level Authorization)API1 (Broken Object Level Authorization)Same
API2 (Broken User Authentication)API2 (Broken Authentication)Renamed, scope widened
API3 (Excessive Data Exposure)API3 (Broken Object Property Level Authorization)Merged with API6
API4 (Lack of Resources & Rate Limiting)API4 (Unrestricted Resource Consumption)Renamed, scope widened
API5 (Broken Function Level Authorization)API5 (Broken Function Level Authorization)Same
API6 (Mass Assignment)API3 (Broken Object Property Level Authorization)Merged with API3
API7 (Security Misconfiguration)API8 (Security Misconfiguration)Renumbered
API8 (Injection)noneLeft the list
API9 (Improper Assets Management)API9 (Improper Inventory Management)Renamed
API10 (Insufficient Logging & Monitoring)noneLeft the list
noneAPI6 (Unrestricted Access to Sensitive Business Flows)New
noneAPI7 (Server Side Request Forgery)New
noneAPI10 (Unsafe Consumption of APIs)New

The first lesson from the table: numbers aren't a stable identity. API6 and API8 describe completely different things in the two editions. Always writing the number together with the edition when recording a finding (API6:2019, API6:2023) prevents this confusion from the start; OWASP's own documents use this format too.

The release notes also contain an honest note about method: for 2023 an open call for data was made for the first time, but no data came in. The list was built from the project team's experience, review by API security specialists and community feedback on the release candidate. So this list is less a statistical ranking and more the experts' answer to "what do we see most often and most expensively in APIs".

The Merger: The Birth of BOPLA

2019's Excessive Data Exposure (returning too much data) and Mass Assignment (accepting too much data) merged into a single item in 2023, API3 BOPLA (Broken Object Property Level Authorization). The reason is that both share the same root cause: missing authorization at the property level. This merger isn't just a renaming; it changes how you think about the defence.

With the 2019 view you'd make two separate fixes: remove fields from the response, reject unknown fields in the request. With the 2023 view you ask a single question: may this role read this field, may it write it? The structure we built in the fourth post answered exactly that question: a response type per role and a writable-field allowlist per role. Most problems that arrive as two separate findings in an old report are two faces of the same design gap and close with a single fix.

The Renamed Ones: When the Name Changes, So Does the Scope

Dropping the word "User" from API2's name looks small but matters: in 2023 authentication is assessed not only for human users but also for services and machines. The API key design and HMAC (Hash-based Message Authentication Code) signed requests from the third post didn't quite fit this heading in 2019's language; in 2023 they're squarely API2's topic.

API4's name went from "lack of resources and rate limiting" to "unrestricted resource consumption". The focus shifted from the number of requests to the cost per request: page size, query complexity, upload size and, most importantly, external services that cost money, such as SMS (Short Message Service), email or LLM (Large Language Model) calls. The plan-based SMS quota from the fifth post wouldn't have fit 2019's heading.

There's a mapping subtlety here. In 2019 a finding "no rate limit on the login endpoint" would be filed under API4. In 2023 API2's prevention list asks for anti-brute-force controls on authentication endpoints that are stricter than general rate limiting. That's why it's more accurate to track a missing limit on an authentication flow under API2 in 2023.

API9 saying "Inventory" instead of "Assets" clarifies the scope too: not only old versions and forgotten hosts, but also which third party the data flows to is part of the inventory.

The Ones That Left: Where Did Injection and Logging Go?

2019's API8 Injection and API10 Insufficient Logging & Monitoring are not on the 2023 list. The OWASP release notes don't give a separate reason; they only remind you that the API list doesn't replace the other Top 10 lists. The practical outcome: these two topics haven't lost importance, they were left to the general list because they aren't API-specific. Injection is tracked today as A05 Injection in the OWASP Top 10:2025, and logging as A09 Security Logging and Alerting Failures; we covered both in detail in the Web Security series.

Closing an injection finding from an old report because "it's not on the list anymore" would be the worst outcome. The right approach is moving it to the Web Top 10 category and, if the data comes from a third party, checking API10 too: putting data returned by a partner API into an SQL (Structured Query Language) query without validating it is both injection and unsafe consumption.

The Newcomers: Flows, SSRF and Other People's APIs

The three new items reflect how APIs changed in recent years. API6 (sensitive business flows) brought flows that are technically flawless but abusable from a business angle onto the list for the first time: bots hoarding limited stock, coupons used again and again. The Idempotency-Key and flow-level limits in the seventh post answer this item.

API7 (SSRF) became an API-specific risk with the spread of webhooks, features that fetch content from a URL (Uniform Resource Locator) and cloud metadata services. In the Web Top 10, SSRF became a separate item in 2021 and was folded under A01 Broken Access Control in 2025; on the API list it stands as an item of its own.

API10 (unsafe consumption) reverses the direction: treating data from third parties we call, or that call us, with as much suspicion as user input. The shipping API and the payment webhook in the eighth post were examples of this item.

Reading an Old Report with the 2023 Categories

Mapping by hand is easy for a few findings and error-prone for hundreds. I added a small tool to the lab: it reads the old report's findings from a CSV (Comma-Separated Values) file, translates them into 2023 categories and lists the 2023 categories the report didn't produce.

// 2019 -> 2023: items that stayed, were renamed, merged or left the list
private static readonly Dictionary<string, (string Category, string Note)> Direct = new()
{
    ["API1:2019"] = ("API1:2023", "unchanged"),
    ["API2:2019"] = ("API2:2023", "renamed: Broken User Authentication -> Broken Authentication"),
    ["API3:2019"] = ("API3:2023", "merged: Excessive Data Exposure -> BOPLA"),
    ["API4:2019"] = ("API4:2023", "renamed: Lack of Resources & Rate Limiting -> Unrestricted Resource Consumption"),
    ["API5:2019"] = ("API5:2023", "unchanged"),
    ["API6:2019"] = ("API3:2023", "merged: Mass Assignment -> BOPLA"),
    ["API7:2019"] = ("API8:2023", "renumbered: Security Misconfiguration"),
    ["API8:2019"] = ("outside", "Injection left the API list: track under OWASP Top 10:2025 A05 Injection"),
    ["API9:2019"] = ("API9:2023", "renamed: Improper Assets Management -> Improper Inventory Management"),
    ["API10:2019"] = ("outside", "Logging left the API list: track under OWASP Top 10:2025 A09 Security Logging and Alerting Failures")
};

private static readonly string[] AuthenticationPaths = ["/login", "/token", "/password-reset", "/account/"];

public static MappedFinding Map(Finding finding)
{
    // A missing limit on an authentication flow is API2's "stricter anti-brute-force controls" item in 2023
    if (finding.Category2019 == "API4:2019"
        && AuthenticationPaths.Any(p => finding.Endpoint.Contains(p, StringComparison.OrdinalIgnoreCase)))
    {
        return new MappedFinding(finding, "API2:2023", "rate limiting on an authentication flow belongs to API2 in 2023");
    }

    (string category, string note) = Direct.TryGetValue(finding.Category2019, out (string Category, string Note) entry)
        ? entry
        : ("unknown", $"unknown 2019 category '{finding.Category2019}'");
    return new MappedFinding(finding, category, note);
}

// 2023 categories with no finding in the old report: not necessarily "clean", possibly "not assessed"
public static IReadOnlyList<string> NotAssessed(IEnumerable<MappedFinding> mapped)
{
    HashSet<string> seen = mapped.Select(m => m.Category2023).ToHashSet();
    return Categories2023.Where(c => !seen.Contains(c)).ToList();
}

For the lab I wrote a fictional pentest report from 2022 with nine findings; most of them resemble problems we ran into in the lab's first version at the start of this series. The tool's output:

$ dotnet run --project tools/Bookstore.Security.ReportMapper
F-01  API1:2019  -> API1:2023   GET /orders/{id}                   unchanged
F-02  API3:2019  -> API3:2023   GET /orders/{id}                   merged: Excessive Data Exposure -> BOPLA
F-03  API6:2019  -> API3:2023   PUT /orders/{id}                   merged: Mass Assignment -> BOPLA
F-04  API4:2019  -> API2:2023   POST /account/password-reset       rate limiting on an authentication flow belongs to API2 in 2023
F-05  API4:2019  -> API4:2023   GET /orders                        renamed: Lack of Resources & Rate Limiting -> Unrestricted Resource Consumption
F-06  API7:2019  -> API8:2023   GET /reports/daily-sales           renumbered: Security Misconfiguration
F-07  API8:2019  -> outside     GET /orders                        Injection left the API list: track under OWASP Top 10:2025 A05 Injection
F-08  API9:2019  -> API9:2023   GET /v1/catalog/books              renamed: Improper Assets Management -> Improper Inventory Management
F-09  API10:2019 -> outside     GET /orders/{id}                   Logging left the API list: track under OWASP Top 10:2025 A09 Security Logging and Alerting Failures

Not assessed by this report: API5:2023, API6:2023, API7:2023, API10:2023

The last line is the most valuable part of the output. API6, API7 and API10 didn't exist in 2019; this report could never have assessed them. API5 was on the list but has no finding in the report: either there really was no problem, or it wasn't tested. You need the report's scope section to know which. These four categories should be written explicitly into the scope of the next test.

The mapping rules are tested too, so someone adding a wrong row to the table gets noticed:

[Fact]
public void Categories_new_in_2023_are_never_covered_by_a_2019_report()
{
    IEnumerable<MappedFinding> all = Enumerable.Range(1, 10)
        .Select(i => ApiTop10Mapping.Map(new Finding("F", $"API{i}:2019", "t", "GET /x")));

    Assert.Equal(["API6:2023", "API7:2023", "API10:2023"], ApiTop10Mapping.NotAssessed(all));
}

With this post the lab's test project reached 194 tests; all green.

When the Next Edition Arrives

As of November 2026 the OWASP API Security project's site shows no edition newer than 2023 and no announced timeline. When a new edition arrives, we'll update this series in three steps. First we'll add a new column to the mapping table in this post and write for each item whether it stayed the same, merged, was renamed or left. Then we'll tie every row of the lab's checklist (the table in the tenth post) to the new category; the defences won't change, the labels will. Finally, for each new item we'll add a defence and a test guarding it to the lab, and write a separate post.

The same approach works in your own project: keep findings and controls with edition-tagged categories, and protect the defences with code and tests independent of the category. A category is a classification; the real work is the tests in the right-hand column of the tenth post's table.

Production Notes

Keep the category in the tracking system as an edition-tagged label rather than free text (like owasp-api:API3:2023). When a new edition arrives, translating labels in bulk is far easier than reading free text one by one.

State explicitly in the pentest contract which edition the test follows. The phrase "according to the OWASP API Top 10" can give a firm still working with the 2019 list in 2026 permission to skip every new category. Add 2023's three new items to the scope explicitly and ask the report to distinguish "tested, no finding" from "not tested" for every category.

Scan and update numbered references in old documents, wiki pages and code comments. If a code comment says "added for API6", a 2023 reader will think it's about sensitive flows, whereas the comment was written for mass assignment.

Common Pitfalls

The first pitfall is mapping by number. API6 and API8 are completely different risks in the two editions; writing the number without the edition is the mistake I run into most often.

The second is closing items that left the list as "no longer important". Injection and logging left the API list but remain in the general Top 10.

The third is treating a category with no finding in the old report as clean. The new categories were never assessed in the old report; that's not a result, it's a scope gap.

The fourth is using the list as a checklist. The Top 10 is an awareness document; if you're looking for a verification standard, OWASP's ASVS (Application Security Verification Standard) is a better fit. We discussed the difference in the last post of the Web Security series.

A Small Experiment

★☆☆ Pick five findings from your own project or a public report and map them from 2019 to 2023 by hand. Then run the tool and compare the results.

★★☆ Add scope information to the tool: have it read the report's "tested categories" list from a separate file and distinguish "tested, no finding" from "not tested".

★★★ Combine the tool's output with the checklist from the tenth post: produce a report listing, for each 2023 category, which tests in the lab guard it. Which category has the fewest tests?

With this post the API Security series ends. The lab has a defence for each of the ten categories and tests guarding it. We'll cover authentication and tokens in the upcoming Authentication and Authorization series, the internals of rate limiting and security headers in the ASP.NET Core Security series, the gateway layer in the API Gateway and YARP (Yet Another Reverse Proxy) series, GraphQL- and gRPC-specific risks in the gRPC and GraphQL series, and LLM APIs in the LLM Application Security series.