Spectral OWASP API Security Ruleset

Phil Sturgeon
by Phil Sturgeon on March 22, 2024 11 min read

The OWASP API Security Project is a research and education project helping API teams discover, define, and categorize security risks. Within that, the API Security Top 10 list ranks the most important risks you should really care about.

To make following the advice easier, Stoplight created the Spectral OWASP ruleset, allowing you to benefit from the advice as you work in Spectral CLI, Stoplight Studio, or many of the other places Spectral runs, initially using the 2019 edition. In July 2023 the OWASP team released a new edition of their API Security Top 10 to cover the biggest threats in 2023, so we have updated our ruleset to match these changes and added some excellent new rules in the process.

API Security Top 10

  1. API1:2023 – Broken Object Level Authorization: APIs tend to expose endpoints that handle object identifiers, creating a wide attack surface of Object Level Access Control issues. Object level authorization checks should be considered in every function that accesses a data source using an ID from the user. This hasn’t changed since 2019.
  2. API2:2023 – Broken Authentication: Authentication mechanisms are often implemented incorrectly, either hand-crafted or misconfigured. This allows attackers to compromise authentication tokens or to exploit implementation flaws to assume other users’ identities temporarily or permanently. Compromising a system’s ability to identify the client/user, compromises API security overall. This hasn’t changed since 2019.
  3. API3:2023 – Broken Object Property Level Authorization: This updated category combines two previous categories: API3:2019 Excessive Data Exposure and API6:2019 – Mass Assignment. It’s focused on the lack of or improper authorization validation at the object property level.
  4. API4:2023 – Unrestricted Resource Consumption: Satisfying API requests requires resources such as network bandwidth, CPU, memory, storage, or integration with third-party services, which charge per email/call/SMS. Successful attacks can lead to Denial of Service or an increase in operational costs. This category recently had a name change.
  5. API5:2023 – Broken Function Level Authorization: Complex access control policies with different hierarchies, groups, roles, and an unclear separation between administrative and regular functions, tend to lead to authorization flaws. By exploiting these issues, attackers can gain access to other users’ resources and/or administrative functions.
  6. API6:2023 – Unrestricted Access to Sensitive Business Flows: APIs vulnerable to this risk expose a business flow – such as buying a ticket, or posting a comment – without compensating for how the functionality could harm the business if used excessively in an automated manner.
  7. API7:2023 – Server-Side Request Forgery: Server-Side Request Forgery (SSRF) flaws can occur when an API fetches a remote resource without validating the user-supplied URI. This enables an attacker to coerce the application to send a crafted request to an unexpected destination, even when protected by a firewall or a VPN.
  8. API8:2023 – Security Misconfiguration: APIs and the systems supporting them typically contain complex configurations, meant to make the APIs more customizable. Software and DevOps engineers can miss these configurations or choose not to follow security best practices when it comes to configuration, opening the door for different types of attacks.
  9. API9:2023 – Improper Inventory Management: APIs tend to expose more endpoints than traditional web applications, making proper and updated documentation highly important. A proper inventory of hosts and deployed API versions is also important to mitigate issues such as deprecated API versions and exposed debug endpoints.
  10. API10:2023 – Unsafe Consumption of APIs: Developers tend to trust data received from third-party APIs more than user input, thus adopting weaker security standards. To compromise APIs, attackers go after integrated third-party services instead of trying to compromise the target API directly.

Added Changes

Let’s focus on some of the changes we’ve made for this new version.

New Rule: owasp:api2:2023-short-lived-access-tokens

Both 2019 and 2023 have been asking people to use strong tokens that rotate, so now if you are using an OAuth 2.x flow which does not mention a refreshUrl, Spectral will ask you for one. Perhaps you are missing it from OpenAPI, but perhaps you are using long-lived tokens that could be hacked. Either way, this rule will check.

components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://example.com/oauth/authorize
          tokenUrl: https://example.com/oauth/token

          # error if this is missing
          refreshUrl: https://example.com/oauth/refresh

New Rule: owasp:api5:2023-admin-security-unique

If you have public endpoints and admin endpoints with the same security requirements, you’ve got a problem. This rule aims to spot anything in the `/admin` namespace that uses any of the same security schemes as the public API, because you do not want users to be able to sneakily work on your admin endpoints.

openapi: "3.1.0"
info:
  version: "1.0"
  title: "My API"
paths:
  "/public/export":
    get:
      security:
      - oauth2: []

  "/admin/export":
    get:
      security:
      - oauth2: [] # this will throw an error

  "/admin/other":
    get:
      security:
      - oauth2: [admin] # this is good

components:
  securitySchemes:
    oauth2:
      type: oauth2
      flows:
        authorizatonCode:
          authorizationUrl: https://example.com/oauth2/authorize
          tokenUrl: https://example.com/oauth2/token
          scopes: {}

New Rule: owasp:api7:2023-concerning-url-parameter

Using external resources based on user input for webhooks, file fetching from URLs, custom SSO, URL previews, or redirects, can lead to a category of security issues that fall under Server-Side Request Forgery. Safe servers can be whitelisted, and URLs can be sanitized and scanned for malicious requests.

This rule will tell Spectral to keep an eye out for any parameters passing URLs to the API. As Spectral can’t tell what you’re doing with those URLs, this rule’s severity is set to Information, which you can choose to ignore either with Overrides or Extends.

    paths:
    "/foo":
        get:
        parameters:
            - name: callback
            in: query
            - name: redirect
            in: query
            - name: redirect_url
            in: query

All of these will trigger the info message.

New Rules: owasp:api3:2023-no-unevaluatedProperties and owasp:api3:2023-constrained-unevaluatedProperties 

This rule is less about a change in OWASP rules. It’s handy for OpenAPI v3.1 users who want to use unevaluatedProperties instead of additionalProperties, as it’s similar and doesn’t have a lot of the confusing drawbacks that stump people when they try to use additionalProperties with allOf.

New Rule: owasp:api8:2023-define-cors-origin

The new API8:2023 — Security Misconfiguration section has collected a lot of the old “make sure you define error responses” and “use HTTPS over HTTP” but this is a net new rule to help remind people to work on their Cross-Origin Resource Sharing (CORS) headers!

The goal of this rule is to get people to define an Access-Control-Allow-Origin header on all responses, whether it is set to *, null, or dash.example.com.

"/":
  get:
    responses:
      "200":
        description: OK
        headers:
          Access-Control-Allow-Origin:
            schema:
              type: string
              examples: ["*"]

CORS is a tricky topic, and there is a whole lot more to it than this one header, but it’s a good place to start.

New rule: owasp:api9:2023-inventory-access

The first entry for API9 – Improper Inventory Management. This rule aims to help people figure out what the intended audience is for a given API, utilizing the increasingly popular x-internal: true/false vendor extension.

servers:

- url: https://api.example.com/
  x-internal: false

- url: https://api-private.example.com/
  x-internal: true

While it might not be a core part of the OpenAPI Specification, it works with most documentation tools, and it won’t hurt to have it in there as anything starting with an x- is ignored by tools that don’t understand it.

New Rule: owasp:api9:2023-inventory-environment

Another new entry for API9 – Improper Inventory Management, this rule asks API developers to be clear about the intended environment of any given server.

servers:

- url: https://api.example.com/
  description: Production

- url: https://preprod.example.com/
  description: Staging

You can call it staging, test, testing, preprod, all the usual names, but if we’ve forgotten anything please do put in a quick pull request.

Limitations

Some of you may have thought of this, but some of those OWASP security concerns are not something Spectral could detect, as it looks at OpenAPI and only describes the surface level of the API. Anything happening inside the code, or SysOps concerns like using an old version of TLS, would all be inaccessible to Spectral.

Spectral can identify issues described in the OpenAPI or highlight what’s missing from the definition, but using it alone will not guarantee your API is completely safe from all forms of attack. Consider it to be one tool in your toolkit for spotting problems rather than a single litmus test.

To learn more about all the Top 10 risks, watch this brilliant YouTube playlist covering the ten categories, put together by Frank Kilcommins and José Haro Peralta for SmartBear last year.

Using the Spectral OWASP Ruleset

If you have not used the Spectral OWASP API Security Ruleset before, you can set it up in a few ways.

Spectral CLI installed via NPM

npm install --save -D @stoplight/spectral-owasp-ruleset@^2.0.0
npm install --save -D @stoplight/spectral-cli

Pop over to your terminal to the working directory that contains your OpenAPI documents and use this command to create a new file that extends the NPM module we just installed.

echo 'extends: ["@stoplight/spectral-owasp-ruleset"]' > .spectral.yaml

Creating this local file acts as a “local ruleset” that extends the distributed ruleset. In its most basic form, this tells Spectral what ruleset you want to use, but it will allow you to customize things, add your own rules, and turn bits off that are causing trouble.

Once the file is in place, you can run spectral lint {doc} to see how your API is faring against these security checks.

spectral lint api/openapi.yaml 

Quick Start with Stoplight Platform

Stoplight Platform comes with a set of public style guides that can be enabled within your Stoplight workspace with a single click. The OWASP Top 10 is one of those and can be enabled through the user interface.

  1. Go to your Stoplight workspace.
  2. Create a style guide project OR edit a project that has an API.
  3. Select Manage Style Guides.
  4. Enable OWASP Top 10 2023 from a list of public style guides.

These rules will then start showing up in Stoplight Studio as you work, letting you know about issues in real time before you even commit anything back. 

Upgrading

If you have already set the OWASP ruleset up via NPM, you can update to this new v2.0.0 version by updating your package.json and running npm update, or run the following command:

npm install --save -D @stoplight/spectral-owasp-ruleset@^2.0.0

For Stoplight Platform users, enable the OWASP Top 10 2023 style guide from the Manage Style Guides option within your workspace. 

Other Changes

Other than the above updates, there are a few other changes to existing rules, mostly focused on changing names to match the categories changing around. These will mostly only affect people who were customizing, extending, or disabling any of the following rules, but keep an eye out for the severity changes.

  • Renamed owasp:api1:2019-no-numeric-ids to owasp:api1:2019-no-numeric-ids
  • Renamed owasp:api2:2019-protection-global-unsafe-strict to owasp:api2:2023-write-restricted
  • Renamed owasp:api2:2019-protection-global-safe to owasp:api2:2023-read-restricted and increased severity from info to warn
  • Renamed owasp:api2:2019-auth-insecure-schemes to owasp:api2:2023-auth-insecure-schemes
  • Renamed owasp:api2:2019-jwt-best-practices to owasp:api2:2023-jwt-best-practices
  • Renamed owasp:api2:2019-no-api-keys-in-url to owasp:api2:2023-no-api-keys-in-url
  • Renamed owasp:api2:2019-no-credentials-in-url to owasp:api2:2023-no-credentials-in-url
  • Renamed owasp:api2:2019-no-http-basic to owasp:api2:2023-no-http-basic
  • Renamed owasp:api3:2019-define-error-validation to owasp:api8:2023-define-error-validation
  • Renamed owasp:api3:2019-define-error-responses-401 to owasp:api8:2023-define-error-responses-401
  • Renamed owasp:api3:2019-define-error-responses-500 to owasp:api8:2023-define-error-responses-500
  • Renamed owasp:api4:2019-rate-limit to owasp:api4:2023-rate-limit
  • Renamed owasp:api4:2019-rate-limit-retry-after to owasp:api4:2023-rate-limit-retry-after
  • Renamed owasp:api4:2019-rate-limit-responses-429 to owasp:api4:2023-rate-limit-responses-429
  • Renamed owasp:api4:2019-array-limit to owasp:api4:2023-array-limit
  • Renamed owasp:api4:2019-string-limit to owasp:api4:2023-string-limit
  • Renamed owasp:api4:2019-string-restricted to owasp:api4:2023-string-restricted and downgraded from error to warn
  • Renamed owasp:api4:2019-integer-limit to owasp:api4:2023-integer-limit
  • Renamed owasp:api4:2019-integer-limit-legacy to owasp:api4:2023-integer-limit-legacy
  • Renamed owasp:api4:2019-integer-format to owasp:api4:2023-integer-format
  • Renamed owasp:api6:2019-no-additionalProperties to owasp:api3:2023-no-additionalProperties and restricted rule to only run the oas3_0 format. 
  • Renamed owasp:api6:2019-constrained-additionalProperties to owasp:api3:2023-constrained-additionalProperties  and restricted rule to only run the oas3_0 format. 
  • Renamed owasp:api7:2023-security-hosts-https-oas2 to owasp:api8:2023-no-scheme-http
  • Renamed owasp:api7:2023-security-hosts-https-oas3 to owasp:api8:2023-no-server-http

See the CHANGELOG.md for the entire list of changes. 

Share this post

Stoplight to Join SmartBear!

As a part of SmartBear, we are excited to offer a world-class API solution for all developers' needs.

Learn More
The blog CTA goes here! If you don't need a CTA, make sure you turn the "Show CTA Module" option off.

Take a listen to The API Intersection.

Hear from industry experts about how to use APIs and save time, save money, and grow your business.

Listen Now