documentationUrl: https://spec.openlint.org/
rules:
  openapi-component-require-security-schemes:
    description: The API contract MUST include a 'securitySchemes' subsection under the 'components' section.
    message: '{{description}}: {{error}}'
    severity: info
    given: $.components
    then:
      field: securitySchemes
      function: truthy
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-component-require-security-schemes
  openapi-document-owasp-api9-server:
    formats:
    - oas3
    description: The API should declare its servers so all hosts and environments are inventoried — undocumented or stray
      non-production hosts are a common inventory-management risk (OWASP API9).
    message: API should declare its servers (host/environment inventory).
    given: $
    severity: info
    then:
      field: servers
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-document-owasp-api9-server
  openapi-document-owasp-api9-server-oas2:
    formats:
    - oas2
    description: The API should declare its host so all hosts and environments are inventoried — undocumented or stray non-production
      hosts are a common inventory-management risk (OWASP API9).
    message: API should declare its host (host/environment inventory).
    given: $
    severity: info
    then:
      field: host
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-document-owasp-api9-server-oas2
  openapi-info-description-no-eval-tag:
    description: Eval functions MUST not be included in the description of an API, keeping descriptions to just the text that
      is needed, and relying on the rest of the OpenAPI to describe what is possible.
    message: Info Description MUST NOT Have Eval Tag
    severity: info
    given: $.info
    then:
      field: description
      function: pattern
      functionOptions:
        notMatch: ^\b(<eval)\b
    documentationUrl: https://apicommons.org/rules/#openapi-info-description-no-eval-tag
  openapi-info-description-no-script-tag:
    description: Script tags MUST not be included in the description of an API, keeping descriptions to just the text that
      is needed, and relying on the rest of the OpenAPI to describe what is possible.
    message: Info Description MUST NOT Have Script Tag
    severity: info
    given: $.info
    then:
      field: description
      function: pattern
      functionOptions:
        notMatch: ^\b(<script)\b
    documentationUrl: https://apicommons.org/rules/#openapi-info-description-no-script-tag
  openapi-info-owasp-api9-document-version:
    description: The API should declare a version in info.version so every published version is inventoried and retired versions
      can be tracked (OWASP API9 — improper inventory management).
    message: API should declare info.version for inventory management.
    given: $.info
    severity: info
    then:
      field: version
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-info-owasp-api9-document-version
  openapi-operation-get-require-security:
    description: 'Your API should be protected by a `security` rule either at global or operation level. Operations should
      be protected specially when they are tied to non-idempotent HTTP methods like `POST`, `PUT`, `PATCH` and `DELETE`. This
      is done with one or more non-empty `security` rules. Security rules are defined in the `securityScheme` section. An
      example of a security rule applied at global level. ``` security: - BasicAuth: [] paths: /books: {} /users: {} securitySchemes:
      BasicAuth: scheme: http type: basic ``` An example of a security rule applied at operation level, which eventually overrides
      the global one ``` paths: /books: post: security: - AccessToken: [] securitySchemes: BasicAuth: scheme: http type: basic
      AccessToken: scheme: http type: bearer bearerFormat: JWT ```.'
    message: 'The following operation is not protected by a `security` rule: {{path}}'
    severity: info
    given:
    - $.paths.*.get
    then:
    - field: security
      function: schema
      functionOptions:
        schema:
          items:
            type: object
            minProperties: 1
          minItems: 1
          type: array
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-operation-get-require-security
  openapi-operation-require-security:
    description: Check operation security is defined.
    message: Check operation security is defined.
    severity: info
    given: $.paths.*.*
    then:
      field: security
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-operation-require-security
  openapi-operation-require-security-2:
    description: Each API operation should have a security definition referencing the central security scheme express for
      an OpenAPI.
    message: Operations MUST Have a Security Definition
    severity: info
    given: $.paths.*[get,post,patch,put,delete]
    then:
      field: security
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-operation-require-security-2
  openapi-operation-security-use-defined-scheme:
    description: Check operation security uses a defined security scheme.
    message: Check operation security uses a defined security scheme.
    severity: info
    given: $.paths[*][*]..security.*
    then:
      function: schema
      functionOptions:
        schema:
          anyOf:
          - required:
            - bearer_auth
          - required:
            - inference_bearer_auth
    documentationUrl: https://apicommons.org/rules/#openapi-operation-security-use-defined-scheme
  openapi-parameter-avoid-integer-id:
    description: Avoid exposing IDs as an integer, UUIDs or other interoperable strings are preferred.
    message: Avoid exposing IDs as an integer, UUIDs or other interoperable strings are preferred.
    severity: info
    given: $.paths..parameters[*].[?(@property === "name" && (@ === "id" || @ === "ID" || @ === "Id"))]^.schema
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          not:
            properties:
              type:
                const: integer
          properties:
            format:
              const: uuid
    documentationUrl: https://apicommons.org/rules/#openapi-parameter-avoid-integer-id
  openapi-parameter-no-api-keys-in-query:
    description: Query parameters MUST not contain sensitive information, like API tokens or keys.
    message: Query parameters MUST not contain sensitive information, like API tokens or keys.
    severity: info
    given: $.paths.*.*.parameters[?(@.in=='query')].name
    then:
      function: pattern
      functionOptions:
        notMatch: apiKey|token
    documentationUrl: https://apicommons.org/rules/#openapi-parameter-no-api-keys-in-query
  openapi-parameter-owasp-api1-no-numeric-ids:
    description: Path parameters should not be sequential integers (BOLA / object enumeration, OWASP API1) — use a non-guessable
      identifier such as a UUID.
    message: Path parameter should not be an integer (use a non-enumerable id, e.g. UUID).
    given: $.paths[*][*].parameters[?(@ && @.in == 'path')].schema
    severity: info
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          properties:
            type:
              not:
                enum:
                - integer
                - number
    documentationUrl: https://apicommons.org/rules/#openapi-parameter-owasp-api1-no-numeric-ids
  openapi-path-no-technology-leak-in:
    description: A resource MUST NOT leak or expose format or technology-specific information at any point in the path.
    message: A resource MUST NOT leak or expose format or technology-specific information at any point in the path.
    severity: info
    given: $.paths.*~
    then:
      function: pattern
      functionOptions:
        notMatch: (.php|.asp|.jsp|.cgi|.psp|.json|.xml)
    documentationUrl: https://apicommons.org/rules/#openapi-path-no-technology-leak-in
  openapi-response-cors-allow-origin-no-wildcard:
    description: 'If an Access-Control-Allow-Origin response header is documented, it should not hard-code a wildcard (*)
      — reflect specific allowed origins instead, especially for authenticated APIs (OWASP API8 security misconfiguration).
      Note: the project treats CORS as operational (see no-operational-headers-in-spec); this is a defensive check for specs
      that do document it.'
    message: Access-Control-Allow-Origin should not be a wildcard (*).
    given: $..responses.*.headers['Access-Control-Allow-Origin'].schema
    severity: info
    then:
      function: schema
      functionOptions:
        schema:
          not:
            anyOf:
            - required:
              - const
              properties:
                const:
                  const: '*'
            - required:
              - default
              properties:
                default:
                  const: '*'
            - required:
              - example
              properties:
                example:
                  const: '*'
    documentationUrl: https://apicommons.org/rules/#openapi-response-cors-allow-origin-no-wildcard
  openapi-response-delete-define-401:
    description: DELETE operations should define a 401 Unauthorized response to document authentication requirements for destructive
      operations.
    message: DELETE MUST Have 401 Response
    severity: info
    given: $.paths[*].delete.responses
    then:
      field: '401'
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-response-delete-define-401
  openapi-response-get-define-401:
    description: GET operations should define a 401 Unauthorized response. Analysis of 773 specs shows 401 is the second most
      common response code with 4805 occurrences, confirming authentication errors must be documented.
    message: GET MUST Have 401 Response
    severity: info
    given: $.paths[*].get.responses
    then:
      field: '401'
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-response-get-define-401
  openapi-response-no-sensitive-data-in-header:
    description: Headers MUST NOT contain sensitive data.
    message: Headers MUST NOT contain sensitive data.
    severity: info
    given: $.paths[*][*].responses[*].headers.*~
    then:
      function: pattern
      functionOptions:
        notMatch: ^(SPS-Token|SPS-Password|SPS-Identity|Password)$
    documentationUrl: https://apicommons.org/rules/#openapi-response-no-sensitive-data-in-header
  openapi-response-owasp-api3-define-error-validation:
    description: Write operations (POST/PUT/PATCH) should define a 400 or 422 validation error response (OWASP API3 — reject
      malformed or unexpected properties).
    message: Write operations should define a 400 or 422 validation error response.
    given: $.paths[*][post,put,patch].responses
    severity: info
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          anyOf:
          - required:
            - '400'
          - required:
            - '422'
    documentationUrl: https://apicommons.org/rules/#openapi-response-owasp-api3-define-error-validation
  openapi-response-owasp-api8-define-error-401:
    description: Operations should define a 401 Unauthorized response (OWASP API8 — security misconfiguration; document auth
      failures).
    message: Operation should define a 401 Unauthorized response.
    given: $.paths[*][get,post,put,patch,delete].responses
    severity: info
    then:
      field: '401'
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-response-owasp-api8-define-error-401
  openapi-response-owasp-api8-define-error-500:
    description: Operations should define a 500 Internal Server Error response (OWASP API8 — document server-error behavior).
    message: Operation should define a 500 Internal Server Error response.
    given: $.paths[*][get,post,put,patch,delete].responses
    severity: info
    then:
      field: '500'
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-response-owasp-api8-define-error-500
  openapi-response-post-define-401:
    description: POST operations should define a 401 Unauthorized response to document authentication requirements for write
      operations.
    message: POST MUST Have 401 Response
    severity: info
    given: $.paths[*].post.responses
    then:
      field: '401'
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-response-post-define-401
  openapi-response-put-define-401:
    description: PUT operations should define a 401 Unauthorized response to document authentication requirements for update
      operations.
    message: PUT MUST Have 401 Response
    severity: info
    given: $.paths[*].put.responses
    then:
      field: '401'
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-response-put-define-401
  openapi-response-success-require-ratelimit-header:
    description: 'Ratelimiting API preserves a service and limits attack scenario [see API4:2019 Lack of Resources & Rate
      Limiting](https://owasp.org/www-project-api-security). APIs should use the following headers at least on successful
      responses: - `X-RateLimit-Limit`: number of total requests in a give time window - `X-RateLimit-Remaining`: remaining
      requests in the current window - `X-RateLimit-Reset`: number of seconds before the window resets An example set of headers
      is the following ``` X-Ratelimit-Limit: 100 X-Ratelimit-Remaining: 40 X-Ratelimit-Reset: 12 ``` A standardization proposal
      for ratelimit headers is ongoning inside the IETF HTTPAPI Workgroup. See [the draft](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/).'
    message: Missing ratelimit headers. {{property}} {{error}} {{path}}
    severity: info
    given: $.[responses][?(@property[0] == "2" )][headers]
    then:
    - functionOptions:
        properties:
        - X-RateLimit-Limit
        - RateLimit-Limit
      function: xor
    - functionOptions:
        properties:
        - X-RateLimit-Remaining
        - RateLimit-Remaining
      function: xor
    - functionOptions:
        properties:
        - X-RateLimit-Reset
        - RateLimit-Reset
      function: xor
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-response-success-require-ratelimit-header
  openapi-schema-array-require-min-max-items:
    description: 'Array size should be limited to mitigate resource exhaustion attacks. This can be done using `maxItems`
      and `minItems`, like in the example below. ``` Limited: type: array maxItems: 10 items: type: string format: date ```
      You should ensure that the schema referenced in `items` is constrained too. If you delegate input validation to a library
      or framework, be sure to test it thoroughly and ensure that it verifies `maxItems`.'
    message: Schema of type array must specify maxItems and minItems. {{path}} {{error}}
    severity: info
    given:
    - $.[?(@.type=="array")]
    then:
    - field: maxItems
      function: defined
    - field: minItems
      function: defined
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-array-require-min-max-items
  openapi-schema-number-require-min-max:
    description: Numeric values should be limited in size to mitigate resource exhaustion using `maximum` and `minimum`. If
      you delegate input validation to a library or framework, be sure to test it thoroughly.
    message: Schema of type number or integer must specify a maximum and a minimum. {{path}} {{error}}
    severity: info
    given:
    - $.[?(@.type=="number")]
    - $.[?(@.type=="integer")]
    then:
    - field: maximum
      function: defined
    - field: minimum
      function: defined
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-number-require-min-max
  openapi-schema-object-constrain-additional-property:
    description: 'By default, jsonschema allows additionalProperties. This means that schema validators can be bypassed using
      further, unspecified fields. While forbidding additionalProperties can create rigidity and hinder the evolution of an
      API - eg making it hard to accept new parameters or fields - it is possible that this flexibility can be used to bypass
      the schema validator and force the application to process unwanted information. Disable `additionalProperties` with
      `false` ``` Person: type: object additionalProperties: false properties: given_name: type: string pattern: [a-zA-Z ]{24}
      ``` Or constraint them using `maxProperties` ``` Person: type: object additionalProperties: type: string pattern: /+39[0-9]{,14}/
      maxProperties: 3 properties: given_name: type: string pattern: [a-zA-Z ]{24} ``` - no additionalProperties - constrained
      additionalProperties.'
    message: 'Objects should not allow additionalProperties. Disable them with `additionalProperties: false` or constraint
      them.'
    severity: info
    given:
    - $.[?(@.type=="object" && @.additionalProperties &&  @.additionalProperties!=true &&  @.additionalProperties!=false )]
    then:
    - field: maxProperties
      function: defined
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-object-constrain-additional-property
  openapi-schema-object-disallow-additional-property:
    description: 'By default, jsonschema allows additionalProperties. This means that schema validators can be bypassed using
      further, unspecified fields. While forbidding additionalProperties can create rigidity and hinder the evolution of an
      API - eg making it hard to accept new parameters or fields - it is possible that this flexibility can be used to bypass
      the schema validator and force the application to process unwanted information. Disable `additionalProperties` with
      `false` ``` Person: type: object additionalProperties: false properties: given_name: type: string pattern: [a-zA-Z ]{24}
      ``` Or constraint them using `maxProperties` ``` Person: type: object additionalProperties: type: string pattern: /+39[0-9]{,14}/
      maxProperties: 3 properties: given_name: type: string pattern: [a-zA-Z ]{24} ``` - no additionalProperties - constrained
      additionalProperties.'
    message: 'Objects should not allow additionalProperties. Disable them with `additionalProperties: false` or constraint
      them.'
    severity: info
    given:
    - $.[?(@.type=="object" && @.additionalProperties==true)]
    then:
    - field: additionalProperties
      function: falsy
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-object-disallow-additional-property
  openapi-schema-object-set-additional-property:
    description: 'By default, jsonschema allows additionalProperties. This means that schema validators can be bypassed using
      further, unspecified fields. While forbidding additionalProperties can create rigidity and hinder the evolution of an
      API - eg making it hard to accept new parameters or fields - it is possible that this flexibility can be used to bypass
      the schema validator and force the application to process unwanted information. Disable `additionalProperties` with
      `false` ``` Person: type: object additionalProperties: false properties: given_name: type: string pattern: [a-zA-Z ]{24}
      ``` Or constraint them using `maxProperties` ``` Person: type: object additionalProperties: type: string pattern: /+39[0-9]{,14}/
      maxProperties: 3 properties: given_name: type: string pattern: [a-zA-Z ]{24} ``` - no additionalProperties - constrained
      additionalProperties. @.additionalProperties)]`).'
    message: 'Objects should not allow additionalProperties. Disable them with `additionalProperties: false` or constraint
      them.'
    severity: info
    given:
    - $.[?(@.type=="object" && ! @.additionalProperties)]
    then:
    - field: additionalProperties
      function: defined
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-object-set-additional-property
  openapi-schema-owasp-api4-integer-format:
    description: Integer properties should declare a format (int32 / int64) so their range is bounded (OWASP API4 — unrestricted
      resource consumption).
    message: Integer property should declare a format (int32 or int64).
    given: $..properties[?(@ && @.type == 'integer')]
    severity: info
    then:
      field: format
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-schema-owasp-api4-integer-format
  openapi-schema-string-require-max-length:
    description: 'String length should be limited to avoid an attacker to send very long strings to your service. You can
      do this in different ways: - specify a `maxLength` - constraint the possible values with an `enum` - use a constrained
      `format` like `date` or `date-time`. A constrained string using the `date` format. ``` ConstrainedString: type: string
      format: date ``` Another constrained string using `maxLength`. You can always add further constraints using a `pattern`
      or a `format`. ``` ZipCode: type: string maxLength: 5 pattern: ''[0-9]{5}'' ``` For further security, you can always
      limit string length even in conjunction with `format` and `pattern`.'
    message: Strings (non enum) must specify a maximum length. {{path}} {{error}}
    severity: info
    given:
    - $.[?(@.type=="string" && !@.enum && @.format!="date" && @.format !="date-time" )]
    then:
    - field: maxLength
      function: defined
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-string-require-max-length
  openapi-schema-string-require-pattern-or-format:
    description: 'String length should be limited to avoid an attacker to send very long strings to your service. You can
      do this in different ways: - specify a `maxLength` - constraint the possible values with an `enum` - use a constrained
      `format` like `date` or `date-time`. A constrained string using the `date` format. ``` ConstrainedString: type: string
      format: date ``` Another constrained string using `maxLength`. You can always add further constraints using a `pattern`
      or a `format`. ``` ZipCode: type: string maxLength: 5 pattern: ''[0-9]{5}'' ``` For further security, you can always
      limit string length even in conjunction with `format` and `pattern`.'
    message: Strings (non enum) must specify a pattern or a format. {{path}}
    severity: info
    given:
    - $.[?(@.type=="string" && !@.enum && @.format!="date" && @.format !="date-time" )]
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          anyOf:
          - required:
            - pattern
          - required:
            - format
          additionalProperties: true
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-string-require-pattern-or-format
  openapi-schema-write-operation-require-security:
    description: 'Your API should be protected by a `security` rule either at global or operation level. Operations should
      be protected specially when they are tied to non-idempotent HTTP methods like `POST`, `PUT`, `PATCH` and `DELETE`. This
      is done with one or more non-empty `security` rules. Security rules are defined in the `securityScheme` section. An
      example of a security rule applied at global level. ``` security: - BasicAuth: [] paths: /books: {} /users: {} securitySchemes:
      BasicAuth: scheme: http type: basic ``` An example of a security rule applied at operation level, which eventually overrides
      the global one ``` paths: /books: post: security: - AccessToken: [] securitySchemes: BasicAuth: scheme: http type: basic
      AccessToken: scheme: http type: bearer bearerFormat: JWT ```.'
    message: 'The following non-idempotent operation is not protected by a `security` rule: {{path}}'
    severity: info
    given:
    - $.paths.*[?(@property.match(/^(post|put|patch|delete)/))]
    then:
    - field: security
      function: schema
      functionOptions:
        schema:
          items:
            type: object
            minProperties: 1
          minItems: 1
          type: array
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-schema-write-operation-require-security
  openapi-security-bearer-scheme-require-bearer-format:
    formats:
    - oas3
    description: HTTP bearer security schemes should declare a bearerFormat (e.g. JWT) so consumers know the token type and
      tooling can validate it.
    message: HTTP bearer scheme should declare a bearerFormat (e.g. JWT).
    given: $.components.securitySchemes[?(@ && @.type == 'http' && @.scheme == 'bearer')]
    severity: info
    then:
      field: bearerFormat
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-security-bearer-scheme-require-bearer-format
  openapi-security-jwt-scheme-require-description:
    severity: info
    description: 'Json Web Tokens RFC7519 is a compact, URL-safe means of representing claims to be transferred between two
      parties. JWT can be enclosed in encrypted or signed tokens like JWS and JWE. The [JOSE IANA registry](https://www.iana.org/assignments/jose/jose.xhtml)
      provides algorithms information. RFC8725 describes common pitfalls in the JWx specifications and in their implementations,
      such as: - the ability to ignore algorithms, eg. `{"alg": "none"}`; - using insecure algorithms like `RSASSA-PKCS1-v1_5`
      eg. `{"alg": "RS256"}`. An API using JWT should explicit in the `description` that the implementation conforms to RFC8725.
      ``` components: securitySchemes: JWTBearer: type: http scheme: bearer bearerFormat: JWT description: |- A bearer token
      in the format of a JWS and conformato to the specifications included in RFC8725. ```.'
    message: JWT usage should be detailed in `description` {{error}}.
    given:
    - $.[securitySchemes][?(@.bearerFormat=="jwt" || @.bearerFormat=="JWT")]
    then:
    - field: description
      function: truthy
    - field: description
      function: pattern
      functionOptions:
        match: .*RFC8725.*
    documentationUrl: https://apicommons.org/rules/#openapi-security-jwt-scheme-require-description
  openapi-security-no-http-basic-auth:
    formats:
    - oas3
    description: Consider a more secure alternative to HTTP Basic.
    message: HTTP Basic is an insecure way to pass credentials around, use an alternative.
    severity: info
    given: $.components.securitySchemes[*]
    then:
      field: scheme
      function: pattern
      functionOptions:
        notMatch: basic
    documentationUrl: https://apicommons.org/rules/#openapi-security-no-http-basic-auth
  openapi-security-no-http-basic-auth-oas2:
    formats:
    - oas2
    description: 'Consider a more secure alternative to HTTP Basic. In Swagger 2.0 basic auth is declared as a security definition
      with `type: basic`.'
    message: HTTP Basic is an insecure way to pass credentials around, use an alternative.
    severity: info
    given: $.securityDefinitions[*]
    then:
      field: type
      function: pattern
      functionOptions:
        notMatch: ^basic$
    documentationUrl: https://apicommons.org/rules/#openapi-security-no-http-basic-auth-oas2
  openapi-security-oauth-disallow-insecure-flows:
    description: The OAuth2 authorization framework defines various [grant types](https://tools.ietf.org/html/rfc6749#section-1.3),
      most notably the [AuthorizationCode](https://tools.ietf.org/html/rfc6749#section-1.3.1) and the [Client Credentials](https://tools.ietf.org/html/rfc6749#section-1.3.4).
      Some grant types are now considered insecure and MUST not be used, including `implicit` and `password`. The new [OAuth2.1](https://tools.ietf.org/html/draft-ietf-oauth-v2-1-01)
      still in draft, removes them and suggests to replace the `implicit` with `authorizationCode` + PKCE defined in RFC7636.
    message: 'Do not use oauth2 insecure flow: "{{property}}".'
    severity: info
    given:
    - $.[?(@.type=="oauth2")].flows
    then:
    - field: implicit
      function: falsy
    - field: password
      function: falsy
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-security-oauth-disallow-insecure-flows
  openapi-security-oauth-endpoints-require-https:
    description: OAuth2 endpoints must use `https://`.
    message: OAuth endpoints must use https://
    severity: info
    given:
    - $.[securitySchemes][?(@.type=="oauth2")][*].[?(@property.match(/url$/i))]
    then:
    - field: value
      function: pattern
      functionOptions:
        match: ^https://
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-security-oauth-endpoints-require-https
  openapi-security-oauth-flow-require-scopes:
    formats:
    - oas3
    description: OAuth2 flows should define scopes so authorization is granular and least-privilege rather than all-or-nothing.
    message: OAuth2 flow should define at least one scope.
    given: $.components.securitySchemes[?(@ && @.type == 'oauth2')].flows[*]
    severity: info
    then:
      field: scopes
      function: schema
      functionOptions:
        schema:
          type: object
          minProperties: 1
    documentationUrl: https://apicommons.org/rules/#openapi-security-oauth-flow-require-scopes
  openapi-security-oauth-flow-require-scopes-oas2:
    formats:
    - oas2
    description: OAuth2 security definitions should define scopes so authorization is granular and least-privilege rather
      than all-or-nothing. In Swagger 2.0 scopes are declared directly on the oauth2 security definition.
    message: OAuth2 security definition should define at least one scope.
    given: $.securityDefinitions[?(@ && @.type == 'oauth2')]
    severity: info
    then:
      field: scopes
      function: schema
      functionOptions:
        schema:
          type: object
          minProperties: 1
    documentationUrl: https://apicommons.org/rules/#openapi-security-oauth-flow-require-scopes-oas2
  openapi-security-oauth-scheme-require-description:
    severity: info
    description: 'Json Web Tokens RFC7519 is a compact, URL-safe means of representing claims to be transferred between two
      parties. JWT can be enclosed in encrypted or signed tokens like JWS and JWE. The [JOSE IANA registry](https://www.iana.org/assignments/jose/jose.xhtml)
      provides algorithms information. RFC8725 describes common pitfalls in the JWx specifications and in their implementations,
      such as: - the ability to ignore algorithms, eg. `{"alg": "none"}`; - using insecure algorithms like `RSASSA-PKCS1-v1_5`
      eg. `{"alg": "RS256"}`. An API using JWT should explicit in the `description` that the implementation conforms to RFC8725.
      ``` components: securitySchemes: JWTBearer: type: http scheme: bearer bearerFormat: JWT description: |- A bearer token
      in the format of a JWS and conformato to the specifications included in RFC8725. ```.'
    message: JWT usage should be detailed in `description` {{error}}.
    given:
    - $.[securitySchemes][?(@.type=="oauth2")]
    then:
    - field: description
      function: truthy
    - field: description
      function: pattern
      functionOptions:
        match: .*RFC8725.*
    documentationUrl: https://apicommons.org/rules/#openapi-security-oauth-scheme-require-description
  openapi-security-openidconnect-require-url:
    formats:
    - oas3
    description: OpenID Connect security schemes should declare an openIdConnectUrl pointing at the discovery document so
      clients can configure themselves.
    message: openIdConnect scheme should declare an openIdConnectUrl.
    given: $.components.securitySchemes[?(@ && @.type == 'openIdConnect')]
    severity: info
    then:
      field: openIdConnectUrl
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-security-openidconnect-require-url
  openapi-security-openidconnect-url-https:
    formats:
    - oas3
    description: The OpenID Connect discovery URL (openIdConnectUrl) should use https so token/identity configuration is not
      retrieved over an insecure channel.
    message: openIdConnectUrl should use https.
    given: $.components.securitySchemes[?(@ && @.type == 'openIdConnect')].openIdConnectUrl
    severity: info
    then:
      function: pattern
      functionOptions:
        match: ^https://
    documentationUrl: https://apicommons.org/rules/#openapi-security-openidconnect-url-https
  openapi-security-owasp-api2-auth-insecure-schemes:
    formats:
    - oas3
    description: HTTP auth schemes should not use insecure mechanisms such as negotiate or oauth1 (OWASP API2). Prefer bearer
      with a vetted token.
    message: HTTP auth scheme is insecure (avoid negotiate / oauth1).
    given: $.components.securitySchemes[?(@ && @.type == 'http')].scheme
    severity: info
    then:
      function: pattern
      functionOptions:
        notMatch: ^(negotiate|oauth)$
    documentationUrl: https://apicommons.org/rules/#openapi-security-owasp-api2-auth-insecure-schemes
  openapi-security-owasp-api2-no-api-keys-in-url:
    formats:
    - oas3
    description: API key security schemes should be sent in a header or cookie, never in the query string or path (OWASP API2
      — credentials leak into logs and history).
    message: apiKey scheme should be in a header or cookie, not the URL.
    given: $.components.securitySchemes[?(@ && @.type == 'apiKey')]
    severity: info
    then:
      field: in
      function: enumeration
      functionOptions:
        values:
        - header
        - cookie
    documentationUrl: https://apicommons.org/rules/#openapi-security-owasp-api2-no-api-keys-in-url
  openapi-security-owasp-api2-no-api-keys-in-url-oas2:
    formats:
    - oas2
    description: 'API key security definitions should be sent in a header, never in the query string (OWASP API2 — credentials
      leak into logs and history). Swagger 2.0 apiKey definitions may only be `in: header` or `in: query`.'
    message: apiKey definition should be in a header, not the query string.
    given: $.securityDefinitions[?(@ && @.type == 'apiKey')]
    severity: info
    then:
      field: in
      function: enumeration
      functionOptions:
        values:
        - header
    documentationUrl: https://apicommons.org/rules/#openapi-security-owasp-api2-no-api-keys-in-url-oas2
  openapi-security-require-root:
    description: The API contract MUST include a 'security' section at the root level.
    message: '{{description}}: {{error}}'
    severity: info
    given: $
    then:
      field: security
      function: truthy
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-security-require-root
  openapi-security-require-root-scheme:
    description: Security field MUST be present at the root of the spec with at least one item (ie. HTTPBearer, Token, APIKey,
      etc.).
    message: Security field MUST be present at the root of the spec with at least one item (ie.
    severity: info
    given: $
    then:
      field: security
      function: schema
      functionOptions:
        schema:
          type: array
          minItems: 1
    documentationUrl: https://apicommons.org/rules/#openapi-security-require-root-scheme
  openapi-security-scheme-require-description:
    formats:
    - oas3
    description: Every security scheme should declare a description so consumers know how to authenticate (which token, where
      to get it, what scopes).
    message: Security scheme should have a description.
    given: $.components.securitySchemes[*]
    severity: info
    then:
      field: description
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-security-scheme-require-description
  openapi-security-scheme-require-description-oas2:
    formats:
    - oas2
    description: Every security definition should declare a description so consumers know how to authenticate (which token,
      where to get it, what scopes).
    message: Security definition should have a description.
    given: $.securityDefinitions[*]
    severity: info
    then:
      field: description
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-security-scheme-require-description-oas2
  openapi-server-must-use-https:
    description: Servers MUST be https and no other protocol is allowed unless using localhost.
    message: Servers MUST be https and no other protocol is allowed unless using localhost.
    severity: info
    given: $.servers..url
    then:
      function: pattern
      functionOptions:
        match: ^(https:|http://localhost)
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-server-must-use-https
  openapi-server-require-https:
    description: ALL requests MUST go through `https` protocol only.
    message: Servers MUST be https and no other protocol is allowed.
    severity: info
    given: $.servers..url
    then:
      function: pattern
      functionOptions:
        match: /^https:/
    formats:
    - oas3
    documentationUrl: https://apicommons.org/rules/#openapi-server-require-https
  openapi-server-require-https-2:
    formats:
    - oas3
    description: 'Servers must use https to ensure the origin of the responses and protect the integrity and the confidentiality
      of the communication. You can use `http://` only on sandboxes environment. Use `x-sandbox: true` to skip this kind of
      check.'
    message: 'Non-sandbox url  {{value}} {{error}}. Add `x-sandbox: true` to skip this check on a specific server.'
    severity: info
    given:
    - $.servers[?(@["x-sandbox"] != true)]
    - $.paths..servers[?(@["x-sandbox"] != true)]
    then:
      field: url
      function: pattern
      functionOptions:
        match: ^https://.*
    documentationUrl: https://apicommons.org/rules/#openapi-server-require-https-2
  openapi-server-require-https-2-oas2:
    formats:
    - oas2
    description: The API must be served over https to protect the integrity and confidentiality of the communication. In Swagger
      2.0 the transport is declared in the root `schemes` array — it should contain `https` and must not contain `http`.
    message: API `schemes` should use https and not http.
    severity: info
    given: $
    then:
      field: schemes
      function: schema
      functionOptions:
        dialect: draft7
        schema:
          type: array
          contains:
            const: https
          not:
            contains:
              const: http
    documentationUrl: https://apicommons.org/rules/#openapi-server-require-https-2-oas2
  openapi-server-url-require-https:
    formats:
    - oas3
    description: API server URLs should use HTTPS to ensure encrypted communication between clients and servers, protecting
      sensitive data in transit.
    message: Server URL MUST Use HTTPS
    severity: info
    given: $.servers[*]
    then:
      field: url
      function: pattern
      functionOptions:
        match: ^https://
    documentationUrl: https://apicommons.org/rules/#openapi-server-url-require-https
  openapi-server-url-require-https-oas2:
    formats:
    - oas2
    description: The API should be served over HTTPS to ensure encrypted communication between clients and servers. In Swagger
      2.0 declare `https` in the root `schemes` array and avoid `http`.
    message: Transport MUST Use HTTPS
    severity: info
    given: $
    then:
      field: schemes
      function: schema
      functionOptions:
        dialect: draft7
        schema:
          type: array
          contains:
            const: https
          not:
            contains:
              const: http
    documentationUrl: https://apicommons.org/rules/#openapi-server-url-require-https-oas2
  openapi-agentic-access-contract-declared:
    description: Every operation exposed to AI agents should declare an x-agentic-access execution contract so an agent knows
      what it may attempt, and what must be denied, constrained, or escalated.
    message: Operation has no x-agentic-access contract — an agent cannot know what it may attempt.
    severity: info
    given: $.paths[*][get,post,put,patch,delete,options,head,trace]
    then:
      field: x-agentic-access
      function: truthy
    documentationUrl: https://apicommons.org/rules/#openapi-agentic-access-contract-declared
  openapi-agentic-access-consequence-requirements:
    description: Higher-consequence actions must bind an audience, require a subject, cap token lifetime, and be audited —
      just-enough privilege, just-in-time access, and an auditable production loop.
    message: Higher-consequence action must bind audience, require a subject, cap token TTL, and be audited.
    severity: info
    given: $.paths[*][get,post,put,patch,delete,options,head,trace].x-agentic-access
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          allOf:
          - if:
              properties:
                consequence:
                  const: write
            then:
              required:
              - audience
              - audit
              - token
              properties:
                audit:
                  const: required
                token:
                  required:
                  - max-ttl
                  properties:
                    max-ttl:
                      maximum: 900
          - if:
              properties:
                consequence:
                  const: physical
            then:
              required:
              - audience
              - audit
              - subject
              - token
              properties:
                subject:
                  const: required
                audit:
                  const: required
                token:
                  required:
                  - max-ttl
                  properties:
                    max-ttl:
                      maximum: 300
          - if:
              properties:
                consequence:
                  const: safety-critical
            then:
              required:
              - audience
              - audit
              - subject
              - token
              properties:
                subject:
                  const: required
                audit:
                  const: required
                token:
                  required:
                  - max-ttl
                  properties:
                    max-ttl:
                      maximum: 120
    documentationUrl: https://apicommons.org/rules/#openapi-agentic-access-consequence-requirements
  openapi-agentic-access-safety-critical-human:
    description: Safety-critical actions must require human-in-the-loop approval — step-up review for high-impact operations.
    message: Safety-critical action must set escalation.human-in-the-loop = required.
    severity: info
    given: $.paths[*][get,post,put,patch,delete,options,head,trace].x-agentic-access
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          if:
            properties:
              consequence:
                const: safety-critical
            required:
            - consequence
          then:
            required:
            - escalation
            properties:
              escalation:
                type: object
                required:
                - human-in-the-loop
                properties:
                  human-in-the-loop:
                    const: required
    documentationUrl: https://apicommons.org/rules/#openapi-agentic-access-safety-critical-human
  openapi-agentic-access-delegation-token-exchange:
    description: Actions that act on behalf of a subject should require token exchange so delegation is scoped per action
      rather than relying on a broad standing token.
    message: Action acts on behalf of a subject but does not require token.exchange = true.
    severity: info
    given: $.paths[*][get,post,put,patch,delete,options,head,trace].x-agentic-access
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          if:
            properties:
              subject:
                const: required
            required:
            - subject
          then:
            required:
            - token
            properties:
              token:
                type: object
                required:
                - exchange
                properties:
                  exchange:
                    const: true
    documentationUrl: https://apicommons.org/rules/#openapi-agentic-access-delegation-token-exchange
  openapi-agentic-access-oauth-protected:
    description: Delegated or acting operations must carry a security requirement so agent actions are actually authorized
      at runtime, not merely described.
    message: Delegated/acting operation for an agent declares no security requirement.
    severity: info
    given: $.paths[*][get,post,put,patch,delete,options,head,trace]
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          if:
            required:
            - x-agentic-access
            properties:
              x-agentic-access:
                required:
                - action-class
                properties:
                  action-class:
                    enum:
                    - acting
                    - delegated
          then:
            required:
            - security
            properties:
              security:
                type: array
                minItems: 1
    documentationUrl: https://apicommons.org/rules/#openapi-agentic-access-oauth-protected
  apis-json-api-baseurl-https:
    description: Each API baseURL should be an https URL.
    message: API baseURL should use https.
    given: $.apis[*].baseURL
    severity: info
    then:
      function: pattern
      functionOptions:
        match: ^https://
    documentationUrl: https://apicommons.org/rules/#apis-json-api-baseurl-https
  apis-json-api-property-require-security-page:
    description: This property ensures there is a URL to the security page, providing details about how security is handled
      for an API.
    message: Has Security Path
    severity: info
    given:
    - $.apis.*.properties.*
    - $.common.*
    then:
    - field: type
      function: pattern
      functionOptions:
        notMatch: \b(Security|SecurityTesting)\b
    documentationUrl: https://apicommons.org/rules/#apis-json-api-property-require-security-page
  apis-json-api-property-url-https:
    description: API property URLs (documentation, OpenAPI, etc.) should be https.
    message: API property url should use https.
    given: $.apis[*].properties[*].url
    severity: info
    then:
      function: pattern
      functionOptions:
        match: ^https://
    documentationUrl: https://apicommons.org/rules/#apis-json-api-property-url-https
  apis-json-document-apis-json-url-https:
    description: The APIs.json url should be an https URL.
    message: APIs.json url should use https.
    given: $.url
    severity: info
    then:
      function: pattern
      functionOptions:
        match: ^https://
    documentationUrl: https://apicommons.org/rules/#apis-json-document-apis-json-url-https
  apis-json-schema-include-authentication-page:
    description: This property ensures that there is a human readable authentication page available that will provide what
      type of authentication is used and how it can be applied, as well as any services or tooling that API consumers can
      use to troubleshoot authentication with APIs.
    message: Has Authentication
    severity: info
    given:
    - $.apis.*.properties.*
    - $.common.*
    then:
    - field: type
      function: pattern
      functionOptions:
        notMatch: \b(Authentication)\b
    documentationUrl: https://apicommons.org/rules/#apis-json-schema-include-authentication-page
  agent-skill-skill-allowed-tools-array:
    description: If a skill declares allowed-tools, it must be an array of tool names so its capability surface is explicit
      and auditable.
    message: allowed-tools must be an array of tool names.
    severity: info
    given: $.frontmatter['allowed-tools']
    then:
      function: schema
      functionOptions:
        schema:
          type: array
          items:
            type: string
    documentationUrl: https://apicommons.org/rules/#agent-skill-skill-allowed-tools-array
