Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a ruleset to check for common security mistakes #39

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions rulesets/security/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Security ruleset, a collection of security-conscious rules

Authors:
- [`@lornajane`](https://github.com/lornajane) Lorna Mitchell (Redocly)

## What this does and why

A ruleset to pick up on some common API mistakes using linting.
A security mindset means more than a few linting rules - but we hope that they help!

Included in this set are a few defensive data type rules, plus a few others from the OWASP recommendations:

- `rule/no-http-basic` - Don't use HTTP Basic auth
- `rule/operation-security` - Security must be defined at the operation level
- `rule/https-server-urls` - Server URLs must use https
- `rule/limit-string-length` - Avoid overflow errors by setting a maximum length for string values
- `rule/limit-array-length` - Avoid overflow errors by setting a maximum number of array items

What else should be here? Open an issue - or a pull request.

## Code

The following code snippet shows the rules to use:

```yaml
rules:

rule/no-http-basic:
message: HTTP Basic should not be used.
subject:
type: SecurityRequirement
property: scheme
assertions:
notPattern: /basic/i
where:
- subject:
type: SecurityRequirement
assertions:
defined: true
severity: error

rule/operation-security:
message: Security must be defined at the operation level.
subject:
type: Operation
property: security
assertions:
defined: true
severity: warn

rule/https-server-urls:
message: Server URLs must start with "https:".
subject:
type: Server
property: url
assertions:
pattern: /^https:/
severity: error

rule/limit-string-length:
message: Strings must have maxLength defined, or be an enum/const
subject:
type: Schema
assertions:
requireAny:
- maxLength
- enum
- const
where:
- subject:
type: Schema
property: type
assertions:
const: string
defined: true
severity: warn

rule/limit-array-length:
message: Arrays must have a maxItems property
subject:
type: Schema
assertions:
required:
- maxItems
where:
- subject:
type: Schema
property: type
assertions:
const: array
defined: true
severity: warn
```

You can copy and paste this configuration into your own `redocly.yaml` file, and adjust the `severity` settings to suit your use case.

Then run `redocly lint` to apply the linting rules to your API description.

## Examples

Each rule has its own example. Run `redocly lint openapi.yaml` to lint your API description.

## HTTP Basic should not be used

This rule picks up where a security scheme uses a scheme of "Basic" (or "basic").
Avoid using an example like the following:

```yaml
components:
securitySchemes:
LegacyAuth:
type: http
scheme: basic
```

It is recommended to use a scheme such as bearer or digest in your APIs.

## Security must be defined at the operation level

OpenAPI allows security to be defined at the top level of the document, but this rule adds a check that every endpoint has a security definition.
By intentionally securing each endpoint with an appropriate configuration, security mistakes are less likely to occur.

Each operation should look like the example below:

```yaml
operationId: getMuseumHours
security:
summary: Get museum hours
- ReaderAuth
description: Get upcoming museum operating hours.
```

This approach also makes it easier to use tighter security for endpoints with side effects.

## Server URLs must start with "https:"

It is good practice to use HTTPS endpoints to protect any credentials or important information during transit.
This rule identifies any plain `http://` URLs in the server array, such as the following example:

```yaml
servers:
- url: "http://example.com/museum-api/"
```

Correct this problem by using `https://` URLs for all endpoints.

## Strings must have maxLength defined, or be an enum/const

To avoid API endpoints receiving payloads that could cause overflow errors, set limits on the size of the fields that can be accepted or define specific values that can be sent.

All of the following field examples are acceptable:

```yaml
components:
schemas:
TicketType:
description: Type of ticket being purchased. Use `general` for regular museum entry and `event` for tickets to special events.
type: string
enum:
- event
- general
example: event
Delivery:
description: The method of ticket delivery for the purchased ticket.
type: string
const: Digital
Email:
description: Email address for ticket purchaser.
type: string
format: email
maxLength: 120
example: [email protected]
```

Note that the `const` keyword came in with the updated JSON Schema version in OpenAPI 3.1.
For OpenAPI 3.0, use an `enum` field with a single option.

## Arrays must have a maxItems property

Similar to the previous point about setting a maximum string field size, set a realistic limit for the size of the arrays that your endpoints accept.
By setting a maximum array size to a sensible limit, you can avoid having your API endpoints try to process something so large that they cause problems.

The following example shows an array field with a limit set:

```yaml
EventDates:
type: array
maxItems: 4
items:
$ref: "#/components/schemas/Date"
description: List of planned dates for the special event.
```

Pick a limit that's generous for the size of the data that you expect, but small enough that it can be handled without performance implications.

## References

- [OWASP top ten](https://owasp.org/Top10/)
- Published linting rulesets from [Spectral](https://blog.stoplight.io/spectral-owasp-api-2023-security-ruleset) and [Vacuum](https://quobix.com/vacuum/rules/owasp/)
68 changes: 68 additions & 0 deletions rulesets/security/redocly.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
rules:

rule/no-http-basic:
message: HTTP Basic should not be used.
subject:
type: SecurityRequirement
property: scheme
assertions:
notPattern: /basic/i
where:
- subject:
type: SecurityRequirement
assertions:
defined: true
severity: error

rule/operation-security:
message: Security must be defined at the operation level.
subject:
type: Operation
property: security
assertions:
defined: true
severity: off

rule/https-server-urls:
message: Server URLs must start with "https:".
subject:
type: Server
property: url
assertions:
pattern: /^https:/
severity: error

rule/limit-string-length:
message: Strings must have maxLength defined, or be an enum/const
subject:
type: Schema
assertions:
requireAny:
- maxLength
- enum
- const
where:
- subject:
type: Schema
property: type
assertions:
const: string
defined: true
severity: off

rule/limit-array-length:
message: Arrays must have a maxItems property
subject:
type: Schema
assertions:
required:
- maxItems
where:
- subject:
type: Schema
property: type
assertions:
const: array
defined: true
severity: off

Loading