# OpenAPI document linting
Source: https://speakeasy.com/docs/sdks/prep-openapi/linting

import { Table } from "@/mdx/components";



In addition to running validation, Speakeasy lints OpenAPI documents to ensure stylistic validity. By default, the linter runs using a [recommended set of rules](/docs/linting/linting#speakeasy-recommended), which can be extended with the [available ruleset](/docs/linting/linting#available-rulesets). Custom rules can also be written using the Spectral format.

The Speakeasy Linter offers:

- Linting and validation of OpenAPI 3.x documents
- Access to 70+ rules
- Quick start with five out-the-box rulesets: `speakeasy-recommended`, `speakeasy-generation`, `speakeasy-openapi`, `vacuum`, and `owasp`
- Reconfiguration of Speakeasy default rules and rulesets
- Configuration of custom rulesets
- Definition of new rules using the Spectral rule format
- Support for custom functions written in Go and JavaScript

## Usage

Three options are available for running linting:

1. Run manually via the Speakeasy CLI:

```bash
speakeasy lint openapi -s openapi.yaml
```

2. Integrate into a Speakeasy workflow:

```yaml
workflowVersion: "1.0.0"
speakeasyVersion: latest
sources:
  api-source:
    inputs:
      - location: ./openapi.yaml
```

Running `speakeasy run` lints the document as part of the workflow and generates an HTML report accessible from a link in the command output.

By default, these options use the `speakeasy-recommended` ruleset to ensure OpenAPI documents meet the Speakeasy quality bar.

## Configuration

OpenAPI spec linting is fully configurable. Create custom rulesets by selecting from predefined sets or writing new rules. These custom linting rules work throughout the workflow.

Immediately before SDK generation, the `speakeasy-generation` ruleset is always applied to ensure compatibility with the code generator.

Configure linting in a `lint.yaml` document in the `.speakeasy` folder. The `.speakeasy` folder can be located in the same directory as the OpenAPI document, the working directory for running the `speakeasy lint` or `speakeasy run` commands, or the home directory.

Example linting configuration in a `lint.yaml` file:

```yaml
lintVersion: 1.0.0
defaultRuleset: speakeasyBarRuleset
rulesets:
  barRuleset:
    rulesets:
      - speakeasy-generation # Use the speakeasy-generation ruleset as a base
      - customRuleset
    rules:
      validate-enums: {
          severity: warn, # drop the severity of the `validate-enums` rule to avoid blocking the pipeline
        }
  customRuleset:
    rules:
      paths-kebab-case: # A custom rule following the spectral format for a rule
        description: Paths should be kebab-case.
        message: "{{property}} should be kebab-case (lower-case and separated with hyphens)"
        severity: warn
        given: $.paths[*]~
        then:
          functionOptions:
            match: "^(\\/|[a-z0-9-.]+|{[a-zA-Z0-9_]+})+$"
      contact-properties:
        description: Contact object must have "name", "url", and "email".
        given: $.info.contact
        severity: warn
        then:
          - field: name
            function: truthy
          - field: url
            function: truthy
          - field: email
            function: truthy
```

A `lint.yaml` document defines a collection of rulesets that can be chained together or used independently. Define any built-in Speakeasy rulesets, create new rules, modify existing rules, or remix available rules to suit specific needs.

Use rulesets in these ways:

1. Set the `defaultRuleset` in the `lint.yaml` to use by default. This ruleset applies when no ruleset is specified using the `lint` command or `workflow.yaml` file.
2. Pass a ruleset name to the `lint` command with the `-r` argument, for example, `speakeasy lint openapi -r barRuleset -s openapi.yaml`.
3. Define the ruleset for a particular source in the `workflow.yaml` file.

```yaml
workflowVersion: "1.0.0"
speakeasyVersion: latest
sources:
  api-source:
    inputs:
      - location: ./openapi.yaml
    ruleset: barRuleset
```

## Custom rules

Create custom rules most easily using the [Spectral rule format](https://docs.stoplight.io/docs/spectral/d3482ff0ccae9-rules), which defines the rule and its properties as an object.

This format works for overriding built-in rules or defining new rules.

For more complex rules beyond pattern matching or field existence checking, define custom Go or JavaScript functions.

### Custom Go/JavaScript functions

Speakeasy linting builds on [vacuum](https://github.com/daveshanley/vacuum) and supports custom Go or JavaScript functions in rules. The vacuum documentation explains writing custom functions in [JavaScript](https://quobix.com/vacuum/api/custom-javascript-functions/) and [Go](https://quobix.com/vacuum/api/custom-functions/).

After creating custom functions, place them in a directory named `functions` in the `.speakeasy` folder (e.g. `.speakeasy/functions/foo.js`).

## Available rules

The rules available to the Speakeasy Linter are listed below and can be used in custom rulesets or to match and modify default rules in the `lint.yaml` file.

<Table
  data={[
    {
      ruleId: "openapi-tags-alphabetical",
      defaultSeverity: "info",
      description: "Tags must be in alphabetical order.",
    },
    {
      ruleId: "tag-description",
      defaultSeverity: "warn",
      description: "Tag must have a description defined.",
    },
    {
      ruleId: "no-$ref-siblings",
      defaultSeverity: "error",
      description:
        "$ref values cannot be placed next to other properties (like a description).",
    },
    {
      ruleId: "oas3-unused-component",
      defaultSeverity: "warn",
      description: "Check for unused components and bad references.",
    },
    {
      ruleId: "owasp-auth-insecure-schemes",
      defaultSeverity: "error",
      description: "Authentication scheme is considered outdated or insecure.",
    },
    {
      ruleId: "no-http-verbs-in-path",
      defaultSeverity: "warn",
      description: "Path segments must not contain an HTTP verb.",
    },
    {
      ruleId: "operation-4xx-response",
      defaultSeverity: "warn",
      description:
        "Make sure operations return at least one `4xx` error response to help with bad requests.",
    },
    {
      ruleId: "duplicated-entry-in-enum",
      defaultSeverity: "error",
      description: "Enum values must not have duplicate entries.",
    },
    {
      ruleId: "operation-tags",
      defaultSeverity: "warn",
      description: "Operation `tags` are missing or empty.",
    },
    {
      ruleId: "owasp-define-error-responses-401",
      defaultSeverity: "warn",
      description:
        "OWASP API Security recommends defining schemas for all responses, even `401 Unauthorized`",
    },
    {
      ruleId: "oas2-anyOf",
      defaultSeverity: "error",
      description:
        "`anyOf` was introduced in OpenAPI 3.0, cannot be used in OpenAPI 2.0 specs",
    },
    {
      ruleId: "owasp-define-error-responses-429",
      defaultSeverity: "warn",
      description:
        "OWASP API Security recommends defining schemas for all responses, even `429 Too Many Requests`.",
    },
    {
      ruleId: "owasp-no-credentials-in-url",
      defaultSeverity: "error",
      description:
        "URL parameters must not contain credentials such as API key, password, or secret.",
    },
    {
      ruleId: "duplicate-tag",
      defaultSeverity: "error",
      description:
        "Tag names must be unique when converted to class, field, or file names.",
    },
    {
      ruleId: "validate-parameters",
      defaultSeverity: "error",
      description:
        "Validate parameters are unique and have a non-empty `name` property when converted to field names.",
    },
    {
      ruleId: "oas2-operation-formData-consume-check",
      defaultSeverity: "warn",
      description:
        "Operations with `in: formData` parameter must include `application/x-www-form-urlencoded` or `multipart/form-data` in their `consumes` property.",
    },
    {
      ruleId: "oas2-discriminator",
      defaultSeverity: "error",
      description: "Discriminators are used correctly in schemas.",
    },
    {
      ruleId: "oas2-operation-security-defined",
      defaultSeverity: "error",
      description:
        "`security` values must match a scheme defined in `securityDefinitions`.",
    },
    {
      ruleId: "oas2-oneOf",
      defaultSeverity: "error",
      description:
        "`oneOf` was introduced in OpenAPI 3.0, cannot be used in OpenAPI 2.0 specs.",
    },
    {
      ruleId: "operation-tag-defined",
      defaultSeverity: "warn",
      description: "Operation tags must be defined in global tags.",
    },
    {
      ruleId: "oas3-example-external-check",
      defaultSeverity: "warn",
      description: "Examples cannot use `value` and `externalValue` together.",
    },
    {
      ruleId: "oas2-api-host",
      defaultSeverity: "info",
      description: "OpenAPI `host` must be present and a non-empty string.",
    },
    {
      ruleId: "owasp-protection-global-unsafe",
      defaultSeverity: "error",
      description:
        "API should be protected by a `security` rule at either global or operation level.",
    },
    {
      ruleId: "oas3-schema",
      defaultSeverity: "error",
      description: "OpenAPI 3.0 specification is invalid.",
    },
    {
      ruleId: "path-params",
      defaultSeverity: "error",
      description: "Path parameters must be defined and valid.",
    },
    {
      ruleId: "owasp-string-limit",
      defaultSeverity: "error",
      description:
        "String size should be limited to mitigate resource exhaustion attacks.",
    },
    {
      ruleId: "owasp-no-http-basic",
      defaultSeverity: "error",
      description:
        "Security scheme uses HTTP Basic. Use a more secure authentication method like OAuth 2.0.",
    },
    {
      ruleId: "oas2-host-not-example",
      defaultSeverity: "warn",
      description: "Host URL should not point at example.com.",
    },
    {
      ruleId: "validate-enums",
      defaultSeverity: "warn",
      description: "Validate enums are valid for type generation.",
    },
    {
      ruleId: "validate-paths",
      defaultSeverity: "error",
      description: "Validate paths conform to RFC 3986.",
    },
    {
      ruleId: "duplicate-properties",
      defaultSeverity: "error",
      description:
        "Property names must be unique and not empty within an operation when converted to field names.",
    },
    {
      ruleId: "validate-composite-schemas",
      defaultSeverity: "error",
      description:
        "Ensure `anyOf`, `allOf`, and `oneOf` don't contain duplicate references.",
    },
    {
      ruleId: "owasp-protection-global-unsafe-strict",
      defaultSeverity: "info",
      description:
        "Check if the operation is protected at operation level. Otherwise, check the global `security` property.",
    },
    {
      ruleId: "owasp-security-hosts-https-oas3",
      defaultSeverity: "error",
      description:
        "All server interactions MUST use HTTPS, meaning server URLs should begin `https://`.",
    },
    {
      ruleId: "owasp-jwt-best-practices",
      defaultSeverity: "error",
      description:
        "JWTs must explicitly declare support for RFC 8725 in the description.",
    },
    {
      ruleId: "owasp-define-error-responses-500",
      defaultSeverity: "warn",
      description:
        "OWASP API Security recommends defining schemas for all responses, even `500 Internal Server Error`.",
    },
    {
      ruleId: "description-duplication",
      defaultSeverity: "info",
      description: "Description duplication check.",
    },
    {
      ruleId: "no-script-tags-in-markdown",
      defaultSeverity: "error",
      description: "Markdown descriptions must not have `<script>` tags.",
    },
    {
      ruleId: "owasp-rate-limit-retry-after",
      defaultSeverity: "error",
      description:
        "Ensure that any `429` response contains a `Retry-After` header.",
    },
    {
      ruleId: "oas3-valid-schema-example",
      defaultSeverity: "warn",
      description: "If an example has been used, check the schema is valid.",
    },
    {
      ruleId: "typed-enum",
      defaultSeverity: "warn",
      description: "Enum values must respect the specified type.",
    },
    {
      ruleId: "operation-operationId",
      defaultSeverity: "error",
      description: "Every operation must contain an `operationId`.",
    },
    {
      ruleId: "operation-parameters",
      defaultSeverity: "error",
      description: "Operation parameters are unique and non-repeating.",
    },
    {
      ruleId: "validate-requests",
      defaultSeverity: "error",
      description: "Validate request content types are valid MIME types.",
    },
    {
      ruleId: "validate-document",
      defaultSeverity: "error",
      description: "Document must have a `paths` or `webhooks` object.",
    },
    {
      ruleId: "no-ambiguous-paths",
      defaultSeverity: "error",
      description: "Paths need to resolve unambiguously from one another.",
    },
    {
      ruleId: "oas3-api-servers",
      defaultSeverity: "warn",
      description: "Check for valid API servers definition.",
    },
    {
      ruleId: "info-contact",
      defaultSeverity: "warn",
      description: "Info section is missing contact details.",
    },
    {
      ruleId: "paths-kebab-case",
      defaultSeverity: "warn",
      description:
        "Path segments must only use kebab case (no underscores or uppercase).",
    },
    {
      ruleId: "openapi-tags",
      defaultSeverity: "warn",
      description:
        "Top-level spec `tags` must not be empty and must be an array.",
    },
    {
      ruleId: "owasp-array-limit",
      defaultSeverity: "error",
      description:
        "Array size should be limited to mitigate resource exhaustion attacks.",
    },
    {
      ruleId: "oas-schema-check",
      defaultSeverity: "error",
      description: "All document schemas must have a valid type defined.",
    },
    {
      ruleId: "license-url",
      defaultSeverity: "info",
      description: "License should contain a URL.",
    },
    {
      ruleId: "oas2-schema",
      defaultSeverity: "error",
      description: "OpenAPI 2.0 specification is invalid.",
    },
    {
      ruleId: "operation-success-response",
      defaultSeverity: "warn",
      description: "Operation must have at least one `2xx` or `3xx` response.",
    },
    {
      ruleId: "owasp-no-api-keys-in-url",
      defaultSeverity: "error",
      description: "API key has been detected in a URL.",
    },
    {
      ruleId: "info-description",
      defaultSeverity: "error",
      description: "Info section is missing a description.",
    },
    {
      ruleId: "oas3-missing-example",
      defaultSeverity: "warn",
      description: "Ensure everything that can have an example contains one.",
    },
    {
      ruleId: "oas3-host-trailing-slash",
      defaultSeverity: "warn",
      description: "Server URL should not contain a trailing slash.",
    },
    {
      ruleId: "owasp-string-restricted",
      defaultSeverity: "error",
      description:
        "String must specify a `format`, RegEx `pattern`, `enum`, or `const`.",
    },
    {
      ruleId: "owasp-no-additionalProperties",
      defaultSeverity: "warn",
      description:
        "By default, JSON Schema allows additional properties, which can potentially lead to mass assignment issues.",
    },
    {
      ruleId: "contact-properties",
      defaultSeverity: "info",
      description: "Contact details are incomplete.",
    },
    {
      ruleId: "validate-security",
      defaultSeverity: "error",
      description: "Validate security schemes are correct.",
    },
    {
      ruleId: "operation-operationId-unique",
      defaultSeverity: "error",
      description: "Every operation must have a unique `operationId`.",
    },
    {
      ruleId: "validate-types",
      defaultSeverity: "error",
      description: "Ensure data types are valid for generation.",
    },
    {
      ruleId: "validate-consts-defaults",
      defaultSeverity: "warn",
      description: "Ensure `const` and `default` values match their type.",
    },
    {
      ruleId: "operation-singular-tag",
      defaultSeverity: "warn",
      description: "Operation cannot have more than a single tag defined.",
    },
    {
      ruleId: "oas2-api-schemes",
      defaultSeverity: "warn",
      description:
        "OpenAPI host `schemes` must be present and a non-empty array.",
    },
    {
      ruleId: "validate-anyof",
      defaultSeverity: "warn",
      description:
        "`anyOf` should only contain types that are compatible with each other.",
    },
    {
      ruleId: "duplicate-schemas",
      defaultSeverity: "hint",
      description: "Inline object schemas must be unique.",
    },
    {
      ruleId: "missing-examples",
      defaultSeverity: "hint",
      description: "Examples should be provided where possible.",
    },
    {
      ruleId: "no-eval-in-markdown",
      defaultSeverity: "error",
      description: "Markdown descriptions must not have `eval()` statements.",
    },
    {
      ruleId: "oas2-host-trailing-slash",
      defaultSeverity: "warn",
      description: "Host URL should not contain a trailing slash.",
    },
    {
      ruleId: "owasp-no-numeric-ids",
      defaultSeverity: "error",
      description:
        "Use random IDs that cannot be guessed. UUIDs are preferred.",
    },
    {
      ruleId: "duplicate-schema-name",
      defaultSeverity: "error",
      description: "Schema names must be unique when converted to class names.",
    },
    {
      ruleId: "validate-responses",
      defaultSeverity: "error",
      description: "Validate response content types are valid MIME types.",
    },
    {
      ruleId: "path-not-include-query",
      defaultSeverity: "error",
      description: "Path must not include query string.",
    },
    {
      ruleId: "path-declarations-must-exist",
      defaultSeverity: "error",
      description:
        "Path parameter declarations must not be empty, for example, `/api/{}` is invalid.",
    },
    {
      ruleId: "owasp-constrained-additionalProperties",
      defaultSeverity: "warn",
      description:
        "By default, JSON Schema allows additional properties, which can potentially lead to mass assignment issues.",
    },
    {
      ruleId: "operation-description",
      defaultSeverity: "warn",
      description: "Operation description checks.",
    },
    {
      ruleId: "owasp-integer-format",
      defaultSeverity: "error",
      description:
        "Integers should be limited to mitigate resource exhaustion attacks.",
    },
    {
      ruleId: "owasp-integer-limit",
      defaultSeverity: "error",
      description:
        "Integers should be limited with `min` or `max` values to mitigate resource exhaustion attacks.",
    },
    {
      ruleId: "validate-deprecation",
      defaultSeverity: "error",
      description:
        "Ensure correct usage of `x-speakeasy-deprecation-replacement` and `x-speakeasy-deprecation-message` extensions.",
    },
    {
      ruleId: "validate-json-schema",
      defaultSeverity: "error",
      description: "Validate OpenAPI document against JSON Schema.",
    },
    {
      ruleId: "validate-content-type",
      defaultSeverity: "error",
      description: "Validate content type schemas.",
    },
    {
      ruleId: "owasp-define-error-validation",
      defaultSeverity: "warn",
      description:
        "Missing error response for `400`, `422`, or `4XX`. Ensure all errors are documented.",
    },
    {
      ruleId: "owasp-rate-limit",
      defaultSeverity: "error",
      description:
        "Define proper rate limiting to avoid attackers overloading the API.",
    },
    {
      ruleId: "oas3-parameter-description",
      defaultSeverity: "warn",
      description: "Parameter description checks.",
    },
    {
      ruleId: "oas3-host-not-example.com",
      defaultSeverity: "warn",
      description: "Server URL should not point at example.com.",
    },
    {
      ruleId: "component-description",
      defaultSeverity: "warn",
      description: "Component description check.",
    },
    {
      ruleId: "oas3-operation-security-defined",
      defaultSeverity: "error",
      description:
        "`security` values must match a scheme defined in `components.securitySchemes`.",
    },
    {
      ruleId: "path-keys-no-trailing-slash",
      defaultSeverity: "warn",
      description: "Path must not end with a slash.",
    },
    {
      ruleId: "duplicate-operation-name",
      defaultSeverity: "error",
      description:
        "Duplicate operation names can cause SDK method name collisions. An SDK method name combines two parts: `group` and `methodName`, forming `sdk.{group}.{methodName}()`. The `methodName` is derived from `operationId` but can be overridden with `x-speakeasy-name-override`; if neither is provided, it falls back to a name generated from the HTTP path and HTTP method. The optional `group` comes from `x-speakeasy-group`; if absent, `tags` may be used.",
    },
    {
      ruleId: "info-license",
      defaultSeverity: "info",
      description: "Info section should contain a license.",
    },
    {
      ruleId: "owasp-protection-global-safe",
      defaultSeverity: "info",
      description:
        "Check if the operation is protected at operation level. Otherwise, check the global `security` property.",
    },
    {
      ruleId: "operation-operationId-valid-in-url",
      defaultSeverity: "error",
      description: "`operationId` must use URL-friendly characters.",
    },
    {
      ruleId: "validate-servers",
      defaultSeverity: "error",
      description:
        "Validate servers, variables, and `x-speakeasy-server-id` extension.",
    },
    {
      ruleId: "validate-extensions",
      defaultSeverity: "error",
      description: "Validate `x-speakeasy-globals` extension usage.",
    },
    {
      ruleId: "oas2-unused-definition",
      defaultSeverity: "warn",
      description: "Check for unused definitions and bad references.",
    },
    {
      ruleId: "oas2-parameter-description",
      defaultSeverity: "warn",
      description: "Parameter description checks.",
    },
  ]}
  columns={[
    { key: "ruleId", header: "Rule ID" },
    { key: "defaultSeverity", header: "Default Severity" },
    { key: "description", header: "Description" },
  ]}
/>

## Available rulesets

The rulesets available to the Speakeasy Linter are listed below and can be chained in custom rules. These rulesets will be used by default when custom linting configuration is not provided.

### speakeasy-recommended

The Speakeasy Linter uses the `speakeasy-recommended` ruleset by default when no custom ruleset is provided. This ruleset is recommended to ensure OpenAPI documents meet the Speakeasy quality bar.

<Table
  data={[
    { ruleId: "duplicate-schema-name" },
    { ruleId: "duplicate-operation-name" },
    { ruleId: "duplicate-properties" },
    { ruleId: "validate-anyof" },
    { ruleId: "validate-document" },
    { ruleId: "validate-enums" },
    { ruleId: "validate-extensions" },
    { ruleId: "validate-json-schema" },
    { ruleId: "validate-parameters" },
    { ruleId: "validate-requests" },
    { ruleId: "validate-responses" },
    { ruleId: "validate-composite-schemas" },
    { ruleId: "validate-security" },
    { ruleId: "validate-servers" },
    { ruleId: "validate-types" },
    { ruleId: "validate-paths" },
    { ruleId: "validate-deprecation" },
    { ruleId: "duplicate-tag" },
    { ruleId: "validate-consts-defaults" },
    { ruleId: "validate-content-type" },
    { ruleId: "duplicate-schemas" },
    { ruleId: "missing-examples" },
    { ruleId: "path-params" },
    { ruleId: "path-declarations-must-exist" },
    { ruleId: "path-not-include-query" },
    { ruleId: "oas3-operation-security-defined" },
    { ruleId: "typed-enum" },
    { ruleId: "no-eval-in-markdown" },
    { ruleId: "no-script-tags-in-markdown" },
    { ruleId: "operation-operationId-unique" },
    { ruleId: "operation-success-response" },
    { ruleId: "oas3-unused-component" },
    { ruleId: "oas3-host-not-example.com" },
    { ruleId: "operation-operationId" },
    { ruleId: "duplicated-entry-in-enum" },
    { ruleId: "operation-tag-defined" },
  ]}
  columns={[{ key: "ruleId", header: "Rule ID" }]}
/>

### speakeasy-generation

The `speakeasy-generation` ruleset is used when generating an SDK from an OpenAPI document. This set of rules _must_ pass to successfully generate an SDK from an OpenAPI document. This ruleset can't be overridden or reconfigured when using the generator.

Use the `speakeasy-generation` ruleset as appropriate to configure the linter to ensure an OpenAPI document is ready for generation.

<Table
  data={[
    { ruleId: "duplicate-schema-name" },
    { ruleId: "duplicate-operation-name" },
    { ruleId: "duplicate-properties" },
    { ruleId: "validate-anyof" },
    { ruleId: "validate-document" },
    { ruleId: "validate-enums" },
    { ruleId: "validate-extensions" },
    { ruleId: "validate-json-schema" },
    { ruleId: "validate-parameters" },
    { ruleId: "validate-requests" },
    { ruleId: "validate-responses" },
    { ruleId: "validate-composite-schemas" },
    { ruleId: "validate-security" },
    { ruleId: "validate-servers" },
    { ruleId: "validate-types" },
    { ruleId: "validate-paths" },
    { ruleId: "validate-deprecation" },
    { ruleId: "duplicate-tag" },
    { ruleId: "validate-consts-defaults" },
    { ruleId: "validate-content-type" },
    { ruleId: "path-params" },
    { ruleId: "path-declarations-must-exist" },
    { ruleId: "path-not-include-query" },
    { ruleId: "oas3-operation-security-defined" },
    { ruleId: "typed-enum" },
    { ruleId: "no-eval-in-markdown" },
    { ruleId: "no-script-tags-in-markdown" },
    { ruleId: "operation-operationId-unique" },
  ]}
  columns={[{ key: "ruleId", header: "Rule ID" }]}
/>

### speakeasy-openapi

The `speakeasy-openapi` ruleset is a minimal set of rules recommended to ensure OpenAPI documents are generally valid and ready to be used by most of the OpenAPI ecosystem.

<Table
  data={[
    { ruleId: "validate-anyof" },
    { ruleId: "validate-document" },
    { ruleId: "validate-json-schema" },
    { ruleId: "validate-parameters" },
    { ruleId: "validate-requests" },
    { ruleId: "validate-responses" },
    { ruleId: "validate-composite-schemas" },
    { ruleId: "validate-security" },
    { ruleId: "validate-servers" },
    { ruleId: "validate-types" },
    { ruleId: "validate-paths" },
    { ruleId: "validate-deprecation" },
    { ruleId: "validate-consts-defaults" },
    { ruleId: "validate-content-type" },
    { ruleId: "duplicate-schemas" },
    { ruleId: "missing-examples" },
    { ruleId: "path-params" },
    { ruleId: "path-declarations-must-exist" },
    { ruleId: "path-not-include-query" },
    { ruleId: "oas3-operation-security-defined" },
    { ruleId: "typed-enum" },
    { ruleId: "no-eval-in-markdown" },
    { ruleId: "no-script-tags-in-markdown" },
    { ruleId: "operation-operationId-unique" },
    { ruleId: "operation-success-response" },
    { ruleId: "oas3-unused-component" },
    { ruleId: "oas3-host-not-example.com" },
    { ruleId: "operation-operationId" },
    { ruleId: "duplicated-entry-in-enum" },
    { ruleId: "operation-tag-defined" },
  ]}
  columns={[{ key: "ruleId", header: "Rule ID" }]}
/>

### vacuum

The `vacuum` ruleset is provided by the [vacuum project](https://github.com/daveshanley/vacuum), which the Speakeasy Linter is built on top of. This set of rules is recommended to ensure OpenAPI documents meet the vacuum quality bar.

<Table
  data={[
    { ruleId: "operation-success-response" },
    { ruleId: "operation-operationId-unique" },
    { ruleId: "operation-operationId" },
    { ruleId: "operation-parameters" },
    { ruleId: "operation-singular-tag" },
    { ruleId: "operation-tag-defined" },
    { ruleId: "path-params" },
    { ruleId: "contact-properties" },
    { ruleId: "info-contact" },
    { ruleId: "info-description" },
    { ruleId: "info-license" },
    { ruleId: "license-url" },
    { ruleId: "openapi-tags-alphabetical" },
    { ruleId: "openapi-tags" },
    { ruleId: "operation-tags" },
    { ruleId: "operation-description" },
    { ruleId: "component-description" },
    { ruleId: "operation-operationId-valid-in-url" },
    { ruleId: "path-declarations-must-exist" },
    { ruleId: "path-keys-no-trailing-slash" },
    { ruleId: "path-not-include-query" },
    { ruleId: "tag-description" },
    { ruleId: "no-$ref-siblings" },
    { ruleId: "oas3-unused-component" },
    { ruleId: "oas2-unused-definition" },
    { ruleId: "oas2-api-host" },
    { ruleId: "oas2-api-schemes" },
    { ruleId: "oas2-discriminator" },
    { ruleId: "oas2-host-not-example" },
    { ruleId: "oas3-host-not-example.com" },
    { ruleId: "oas2-host-trailing-slash" },
    { ruleId: "oas3-host-trailing-slash" },
    { ruleId: "oas2-parameter-description" },
    { ruleId: "oas3-parameter-description" },
    { ruleId: "oas3-operation-security-defined" },
    { ruleId: "oas2-operation-security-defined" },
    { ruleId: "typed-enum" },
    { ruleId: "duplicated-entry-in-enum" },
    { ruleId: "no-eval-in-markdown" },
    { ruleId: "no-script-tags-in-markdown" },
    { ruleId: "description-duplication" },
    { ruleId: "oas3-api-servers" },
    { ruleId: "oas2-operation-formData-consume-check" },
    { ruleId: "oas2-anyOf" },
    { ruleId: "oas2-oneOf" },
    { ruleId: "no-ambiguous-paths" },
    { ruleId: "no-http-verbs-in-path" },
    { ruleId: "paths-kebab-case" },
    { ruleId: "operation-4xx-response" },
    { ruleId: "oas2-schema" },
    { ruleId: "oas3-schema" },
    { ruleId: "oas3-valid-schema-example" },
    { ruleId: "oas3-missing-example" },
    { ruleId: "oas3-example-external-check" },
    { ruleId: "oas-schema-check" },
  ]}
  columns={[{ key: "ruleId", header: "Rule ID" }]}
/>

### owasp

The `owasp` ruleset is recommended to ensure OpenAPI documents meet the [Open Worldwide Application Security Project (OWASP)](https://owasp.org/www-project-api-security/) quality bar.

<Table
  data={[
    { ruleId: "owasp-protection-global-unsafe" },
    { ruleId: "owasp-protection-global-unsafe-strict" },
    { ruleId: "owasp-protection-global-safe" },
    { ruleId: "owasp-define-error-responses-401" },
    { ruleId: "owasp-define-error-responses-500" },
    { ruleId: "owasp-rate-limit" },
    { ruleId: "owasp-rate-limit-retry-after" },
    { ruleId: "owasp-define-error-responses-429" },
    { ruleId: "owasp-array-limit" },
    { ruleId: "owasp-jwt-best-practices" },
    { ruleId: "owasp-auth-insecure-schemes" },
    { ruleId: "owasp-no-numeric-ids" },
    { ruleId: "owasp-no-http-basic" },
    { ruleId: "owasp-define-error-validation" },
    { ruleId: "owasp-no-api-keys-in-url" },
    { ruleId: "owasp-no-credentials-in-url" },
    { ruleId: "owasp-string-limit" },
    { ruleId: "owasp-string-restricted" },
    { ruleId: "owasp-integer-format" },
    { ruleId: "owasp-integer-limit" },
    { ruleId: "owasp-no-additionalProperties" },
    { ruleId: "owasp-constrained-additionalProperties" },
    { ruleId: "owasp-security-hosts-https-oas3" },
  ]}
  columns={[{ key: "ruleId", header: "Rule ID" }]}
/>