OpenAPI Document Linting

Info Icon

TIP

For editing the lint.yaml file, Speakeasy's VSCode extension (opens in a new tab) provides syntax highlighting and autocompletion for the file, in addition to linting for OpenAPI documents, and our other supported file types.

In addition to running validation, you can use Speakeasy to lint your OpenAPI documents to ensure they are stylistically valid. By default, the linter runs using a recommended set of rules, which you can optionally extend with the available ruleset. Additionally you may write your own custom rules using the Spectral format.

With the Speakeasy Linter, you can:

  • Lint & validate OpenAPI 3.x documents
  • Choose from 70+ rules
  • Get started quickly with 5 out-of-the-box rulesets including speakeasy-recommended, speakeasy-generation, speakeasy-openapi, vacuum & owasp
  • Reconfigure Speakeasy's default rules & rulesets
  • Configure custom rulesets
  • Define new rules via the Spectral rule format
  • Provide custom functions written in Go and JS for custom rules

Usage

There are three options for running linting:

  1. Run manually via the Speakeasy CLI:

speakeasy lint openapi -s openapi.yaml

  1. Integrate into your Speakeasy workflow:

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

then running speakeasy run will lint your document as part of the workflow.

This will generate a HTML report that you can find by clicking on the link output by the command.

  1. In your IDE via Speakeasy's VSCode extension (opens in a new tab)

By default these options use the speakeasy-recommended ruleset to ensure your OpenAPI document meets Speakeasy's quality bar.

Configuration

Linting of an OpenAPI spec is fully configurable. You may create a custom ruleset by picking & choosing from our pre-defined sets or writing you own rules. Your custom linting rules can be used throughout your workflow.

The only exception is immediately prior to SDK generation. In that case, the speakeasy-generation ruleset is always used, to ensure compatibility with the code generator.

This is done through setting up a lint.yaml document in your .speakeasy folder, the folder can either live alongside your openapi document, or in the working directory you are running the speakeasy lint or speakeasy run commands from or in your home directory.

An example linting configuration (lint.yaml) is shown below:


lintVersion: 1.0.0
defaultRuleset: speakeasyBarRuleset
rulesets:
barRuleset:
rulesets:
- speakeasy-generation # Use the speakeasy-generation ruleset as a base
- ourRuleset
rules:
validate-enums: {
severity: warn, # drop the serverity of the `validate-enums` rule as I don't want this to block the pipeline
}
ourRuleset:
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 set of rulesets that can be chained together or used independently. These can define any of our built-in rulesets or any other rulesets defined in the document along with defining new rules to add or existing rules to modify or even just remixing our available rules to only run the ones you need.

Rulesets can be used in a number of different ways:

  1. Set the defaultRuleset in your lint.yaml to the ruleset you want to use by default when this file is present. This will be used if a ruleset is not specified using the other options below.
  2. Pass the ruleset name to the lint command with the -r argument for example speakeasy lint openapi -r barRuleset -s openapi.yaml.
  3. Define the ruleset to use for a particular source in your workflow.yaml file.

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

Custom rules

The easiest way to define a custom rule is to use the Spectral rule format (opens in a new tab). This is an object that defines the rule and its properties.

This format can be used to override any of the builtin rules or to define new rules.

If you need to do anything more complex then matching a pattern or checking a field exists, then you can define a custom function in Go or JS and use that in your rule.

Speakeasy linting is built on top of Vacuum (opens in a new tab) and allows for provding custom functions to be used in rules. These can be written in Go or JS and then used in your rules. Documentation on how to write these functions can be found in the Vacuum documentation for JS (opens in a new tab) and Go (opens in a new tab)

Available Rules

Below is a list of all the available rules available to the Speakeasy Linter. These can be used in your custom rulesets or can be used to match and modify the default rules in your lint.yaml file.

Rule IDDefault SeverityDescription
openapi-tags-alphabeticalinfoTags must be in alphabetical order
tag-descriptionwarnTag must have a description defined
no-$ref-siblingserror$ref values cannot be placed next to other properties (like a description)
oas3-unused-componentwarnCheck for unused components and bad references
owasp-auth-insecure-schemeserrorAuthentication scheme is considered outdated or insecure
no-http-verbs-in-pathwarnPath segments must not contain an HTTP verb
operation-4xx-responsewarnMake sure operations return at least one 4xx error response to help with bad requests
duplicated-entry-in-enumerrorEnum values must not have duplicate entry
operation-tagswarnOperation tags are missing/empty
owasp-define-error-responses-401warnOWASP API Security recommends defining schemas for all responses, even error: 401
oas2-anyOferroranyOf was introduced in OpenAPI 3.0, cannot be used un OpenAPI 2 specs
owasp-define-error-responses-429warnOWASP API Security recommends defining schemas for all responses, even error: 429
owasp-no-credentials-in-urlerrorURL parameters must not contain credentials such as API key, password, or secret.
duplicate-tagerrorTag names must be unique when converted to class/field/file names
validate-parameterserrorValidate parameters are unique and have a non-empty 'name' property when converted to field names
oas2-operation-formData-consume-checkwarnOperations with in: formData parameter must include application/x-www-form-urlencoded or multipart/form-data in their consumes property.
oas2-discriminatorerrordiscriminators are used correctly in schemas
oas2-operation-security-definederrorsecurity values must match a scheme defined in securityDefinitions
oas2-oneOferroroneOf was introduced in OpenAPI 3.0, cannot be used un OpenAPI 2 specs
operation-tag-definedwarnOperation tags must be defined in global tags.
oas3-example-external-checkwarnExamples cannot use both value and externalValue together.
oas2-api-hostinfoOpenAPI host must be present and a non-empty string
owasp-protection-global-unsafeerrorAPI should be protected by a security rule either at global or operation level.
oas3-schemaerrorOpenAPI 3 specification is invalid
path-paramserrorPath parameters must be defined and valid.
owasp-string-limiterrorString size should be limited to mitigate resource exhaustion attacks.
owasp-no-http-basicerrorSecurity scheme uses HTTP Basic. Use a more secure authentication method, like OAuth 2.0
oas2-host-not-examplewarnHost URL should not point at example.com
validate-enumserrorValidate enums are valid for type generation
validate-pathserrorValidate paths conform to RFC 3986
duplicate-propertieserrorProperty names must be unique and not empty within a operation when converted to field names
validate-composite-schemaserrorEnsure anyOf-allOf-oneOf don't contain duplicate references
owasp-protection-global-unsafe-strictinfoCheck if the operation is protected at operation level. Otherwise, check the global security property
owasp-security-hosts-https-oas3errorAll server interactions MUST use the https protocol, meaning server URLs should begin https://.
owasp-jwt-best-practiceserrorJWTs must explicitly declare support for RFC8725 in the description
owasp-define-error-responses-500warnOWASP API Security recommends defining schemas for all responses, even error: 500
description-duplicationinfoDescription duplication check
no-script-tags-in-markdownerrorMarkdown descriptions must not have <script> tags'
owasp-rate-limit-retry-aftererrorEnsure that any 429 response, contains a Retry-After header.
oas3-valid-schema-examplewarnIf an example has been used, check the schema is valid
typed-enumwarnEnum values must respect the specified type
operation-operationIderrorEvery operation must contain an operationId.
operation-parameterserrorOperation parameters are unique and non-repeating.
validate-requestserrorValidate request content types are valid mime types
validate-documenterrorDocument must have a paths or webhooks object
no-ambiguous-pathserrorPaths need to resolve unambiguously from one another
oas3-api-serverswarnCheck for valid API servers definition
info-contactwarnInfo section is missing contact details
paths-kebab-casewarnPath segments must only use kebab-case (no underscores or uppercase)
openapi-tagswarnTop level spec tags must not be empty, and must be an array
owasp-array-limiterrorArray size should be limited to mitigate resource exhaustion attacks.
oas-schema-checkerrorAll document schemas must have a valid type defined
license-urlinfoLicense should contain a URL
oas2-schemaerrorOpenAPI 2 specification is invalid
operation-success-responsewarnOperation must have at least one 2xx or a 3xx response.
owasp-no-api-keys-in-urlerrorAPI Key has been detected in a URL
info-descriptionerrorInfo section is missing a description
oas3-missing-examplewarnEnsure everything that can have an example, contains one
oas3-host-trailing-slashwarnserver URL should not contain a trailing slash
owasp-string-restrictederrorString must specify a format, RegEx pattern, enum, or const
owasp-no-additionalPropertieswarnBy default JSON Schema allows additional properties, which can potentially lead to mass assignment issues.
contact-propertiesinfoContact details are incomplete
validate-securityerrorValidate security schemes are correct
operation-operationId-uniqueerrorEvery operation must have unique operationId.
validate-typeserrorEnsure data types are valid for generation
validate-consts-defaultswarnEnsure consts and defaults match their type
operation-singular-tagwarnOperation cannot have more than a single tag defined
oas2-api-schemeswarnOpenAPI host schemes must be present and non-empty array
validate-anyofwarnanyOf should only contain types which are compatible with each other
duplicate-schemashintInline, object schemas must be unique
missing-exampleshintExamples should be provided where possible
no-eval-in-markdownerrorMarkdown descriptions must not have eval() statements'
oas2-host-trailing-slashwarnHost URL should not contain a trailing slash
owasp-no-numeric-idserrorUse random IDs that cannot be guessed. UUIDs are preferred
duplicate-schema-nameerrorSchema names must be unique when converted to class names
validate-responseserrorValidate response content types are valid mime types
path-not-include-queryerrorPath must not include query string
path-declarations-must-existerrorPath parameter declarations must not be empty ex. /api/{} is invalid
owasp-constrained-additionalPropertieswarnBy default JSON Schema allows additional properties, which can potentially lead to mass assignment issues.
operation-descriptionwarnOperation description checks
owasp-integer-formaterrorIntegers should be limited to mitigate resource exhaustion attacks.
owasp-integer-limiterrorIntegers should be limited via min/max values to mitigate resource exhaustion attacks.
validate-deprecationerrorEnsure correct usage of x-speakeasy-deprecation-replacement and x-speakeasy-deprecation-message extensions
validate-json-schemaerrorValidate OpenAPI document against JSON schema
validate-content-typeerrorValidate content type schemas
owasp-define-error-validationwarnMissing error response of either 400, 422 or 4XX, Ensure all errors are documented.
owasp-rate-limiterrorDefine proper rate limiting to avoid attackers overloading the API.
oas3-parameter-descriptionwarnParameter description checks
oas3-host-not-example.comwarnServer URL should not point at example.com
component-descriptionwarnComponent description check
oas3-operation-security-definederrorsecurity values must match a scheme defined in components.securitySchemes
path-keys-no-trailing-slashwarnPath must not end with a slash
duplicate-operation-iderrorOperation IDs (including inferred) must be unique across all operations and tags, and overridden method names must be unique within tags when converted to method names
info-licenseinfoInfo section should contain a license
owasp-protection-global-safeinfoCheck if the operation is protected at operation level. Otherwise, check the global security property
operation-operationId-valid-in-urlerrorOperationId must use URL friendly characters
validate-serverserrorValidate servers, variables and x-speakeasy-server-id extension
validate-extensionserrorValidate x-speakeasy-globals extension usage
oas2-unused-definitionwarnCheck for unused definitions and bad references
oas2-parameter-descriptionwarnParameter description checks

Available Rulesets

Below is a list of all the available rulesets available to the Speakeasy Linter. These can be chained in your custom rules but get used by default when a custom linting configuration is not provided.

speakeasy-recommended

The speakeasy-recommended ruleset is the default ruleset used by the Speakeasy Linter when no custom ruleset is provided. It is a set of rules that are recommended to be used to ensure your OpenAPI document meets Speakeasy's quality bar.

Rule ID
duplicate-schema-name
duplicate-operation-id
duplicate-properties
validate-anyof
validate-document
validate-enums
validate-extensions
validate-json-schema
validate-parameters
validate-requests
validate-responses
validate-composite-schemas
validate-security
validate-servers
validate-types
validate-paths
validate-deprecation
duplicate-tag
validate-consts-defaults
validate-content-type
duplicate-schemas
missing-examples
path-params
path-declarations-must-exist
path-not-include-query
oas3-operation-security-defined
typed-enum
no-eval-in-markdown
no-script-tags-in-markdown
operation-operationId-unique
operation-success-response
oas3-unused-component
oas3-host-not-example.com
operation-operationId
duplicated-entry-in-enum
operation-tag-defined

speakeasy-generation

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

But you can use it as you see fit when configuring the linter to ensure your document is ready for generation.

Rule ID
duplicate-schema-name
duplicate-operation-id
duplicate-properties
validate-anyof
validate-document
validate-enums
validate-extensions
validate-json-schema
validate-parameters
validate-requests
validate-responses
validate-composite-schemas
validate-security
validate-servers
validate-types
validate-paths
validate-deprecation
duplicate-tag
validate-consts-defaults
validate-content-type
path-params
path-declarations-must-exist
path-not-include-query
oas3-operation-security-defined
typed-enum
no-eval-in-markdown
no-script-tags-in-markdown
operation-operationId-unique

speakeasy-openapi

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

Rule ID
validate-anyof
validate-document
validate-json-schema
validate-parameters
validate-requests
validate-responses
validate-composite-schemas
validate-security
validate-servers
validate-types
validate-paths
validate-deprecation
validate-consts-defaults
validate-content-type
duplicate-schemas
missing-examples
path-params
path-declarations-must-exist
path-not-include-query
oas3-operation-security-defined
typed-enum
no-eval-in-markdown
no-script-tags-in-markdown
operation-operationId-unique
operation-success-response
oas3-unused-component
oas3-host-not-example.com
operation-operationId
duplicated-entry-in-enum
operation-tag-defined

vacuum

The vacuum ruleset is provided by the Vacuum project (opens in a new tab) which the Speakeasy Linter is built on top of. It is a set of rules that are recommended to be used to ensure your OpenAPI document meets Vacuum's quality bar.

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

owasp

The owasp ruleset is a set of rules that are recommended to be used to ensure your OpenAPI document meets the Open Worldwide Application Security Project (OWASP) (opens in a new tab) quality bar.

Rule ID
owasp-protection-global-unsafe
owasp-protection-global-unsafe-strict
owasp-protection-global-safe
owasp-define-error-responses-401
owasp-define-error-responses-500
owasp-rate-limit
owasp-rate-limit-retry-after
owasp-define-error-responses-429
owasp-array-limit
owasp-jwt-best-practices
owasp-auth-insecure-schemes
owasp-no-numeric-ids
owasp-no-http-basic
owasp-define-error-validation
owasp-no-api-keys-in-url
owasp-no-credentials-in-url
owasp-string-limit
owasp-string-restricted
owasp-integer-format
owasp-integer-limit
owasp-no-additionalProperties
owasp-constrained-additionalProperties
owasp-security-hosts-https-oas3