Global 'security' field is not defined

Issue ID: v3-global-security

Average severity: Critical

Description

The global security field of the API has not been defined. This field specifies if your API requires the API consumer to authenticate to use the API.

For more details, see the OpenAPI Specification.

Example

The security field is tightly coupled with the securitySchemes objects. The security field could be missing because:

  • You forgot to define the securitySchemes field altogether, leaving the API completely unprotected.
  • You defined the securitySchemes field but not the security field. The definitions are not actually getting applied.
  • You defined the securitySchemes field and the operation-level security field for some of the API operations. However, you did not define the security field on the global level for the whole API.

Possible exploit scenario

If you do not set the global security field, the API does not require any authentication by default. Anyone can use the API operations that do not have a security field defined. All they need to know is the URL for the API operation and how to invoke it.

This sometimes happens to internal APIs. These are often created only to be used inside the company web pages and mobile applications. No one expects any outsiders to know that the API exists, so developers do not spend time implementing security.

But attackers can look at the code of the mobile or web application, or listen to the API traffic, and reverse engineer how the API works. Once the attackers have figured this out, they can start using the API because it does not require any authentication.

Relying on defining security only on each operation individually is an error-prone approach. It is very easy to forget to set security when you add a new method to the API. If there is no global default security defined, the operation is left wide open for an attacker to invoke without any authentication required.

Remediation

First, define the securitySchemes object on the global level, and list the authentication methods that you plan to use. For example:

{
    "components": {
        "securitySchemes": {
            "OAuth2": {
                "type": "oauth2",
                "flows": {
                    "authorizationCode": {
                        "scopes": {
                            "readOnly": "read objects in your account"
                        },
                        "authorizationUrl": "https://example.com/oauth/authorize",
                        "tokenUrl": "https://example.com/oauth/token" 
                    }
                }
            },
            "apiKey": {
                "type": "apiKey",
                "name": "X-API-Key",
                "in": "cookie"
            }
        }
    }
}

Then, use the security field on the global level to set the default authentication requirements for the whole API.

If you have more than one definition in securitySchemes and you want to apply all of them for each API call, use the following syntax (semantically AND):

{
    "security": [
        { "OAuth2": ["readOnly"], "apiKey": [] }
    ]
}

If you want to apply only one of the definitions to an API call, use the following syntax (semantically OR):

{
    "security": [
        { "OAuth2": ["readOnly"] },
        { "apiKey": [] }
    ]
}

You can add an exception to the security specified on the global level on the operation level as needed. This overrides the authentication requirements of the whole API. Simply add a separate security field to the operation in question.