daveshanley / vacuum

vacuum is the worlds fastest OpenAPI 3, OpenAPI 2 / Swagger linter and quality analysis tool. Built in go, it tears through API specs faster than you can think. vacuum is compatible with Spectral rulesets and generates compatible reports.
https://quobix.com/vacuum
MIT License
611 stars 50 forks source link

OWASP ruleset doesn't seem to work with swagger 2 appspecs as of `v0.7.0` #525

Open TheTeaCat opened 3 months ago

TheTeaCat commented 3 months ago

The out-of-the-box OWASP ruleset doesn't seem to flag anything up in swagger 2 specs as of v0.7.0. For example, the following swagger 2 spec yields no findings (when I run a spectral report, vacuum just writes out null):

Swagger 2 specification ```yaml swagger: '2.0' info: title: My API version: '1.0.0' paths: /profile: get: responses: '200': description: OK '400': description: Bad Request '401': description: Unauthorized '500': description: Internal Server Error ```

However, if I convert it to OpenAPI 3.0.1 at editor.swagger.io:

OpenAPI 3.0.1 equivalent ```yaml openapi: 3.0.1 info: title: My API version: 1.0.0 servers: - url: / paths: /profile: get: responses: "200": description: OK content: {} "400": description: Bad Request content: {} "401": description: Unauthorized content: {} "500": description: Internal Server Error content: {} components: {} x-original-swagger-version: "2.0" ```

Then I get all these findings:

Spectral report from the OpenAPI 3.1.0 specification ```json [ { "code": "owasp-security-hosts-https-oas3", "path": [ "servers", "0", "url" ], "message": "server URLs should use TLS (https)", "severity": 0, "range": { "start": { "line": 6, "character": 5 }, "end": { "line": 6, "character": 8 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-protection-global-safe", "path": [ "paths", "/profile", "get" ], "message": "`security` was not defined for path `/profile` in method `get`", "severity": 3, "range": { "start": { "line": 9, "character": 5 }, "end": { "line": 9, "character": 8 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-define-error-responses-429", "path": [ "paths", "/profile", "get", "responses" ], "message": "missing response code `429` for `GET`", "severity": 1, "range": { "start": { "line": 10, "character": 7 }, "end": { "line": 10, "character": 16 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-rate-limit", "path": [ "paths", "/profile", "get", "responses", "200" ], "message": "response with code `200`, must contain one of the defined headers: `{X-RateLimit-Limit} {X-Rate-Limit-Limit} {RateLimit-Limit, RateLimit-Reset} {RateLimit} `", "severity": 0, "range": { "start": { "line": 11, "character": 9 }, "end": { "line": 11, "character": 12 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-rate-limit", "path": [ "paths", "/profile", "get", "responses", "400" ], "message": "response with code `400`, must contain one of the defined headers: `{X-RateLimit-Limit} {X-Rate-Limit-Limit} {RateLimit-Limit, RateLimit-Reset} {RateLimit} `", "severity": 0, "range": { "start": { "line": 14, "character": 9 }, "end": { "line": 14, "character": 12 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-rate-limit", "path": [ "paths", "/profile", "get", "responses", "401" ], "message": "response with code `401`, must contain one of the defined headers: `{X-RateLimit-Limit} {X-Rate-Limit-Limit} {RateLimit-Limit, RateLimit-Reset} {RateLimit} `", "severity": 0, "range": { "start": { "line": 17, "character": 9 }, "end": { "line": 17, "character": 12 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-define-error-responses-401", "path": [ "paths", "/profile", "get", "responses", "401" ], "message": "missing schema for `401` response on `GET`", "severity": 1, "range": { "start": { "line": 19, "character": 11 }, "end": { "line": 19, "character": 18 } }, "source": "swagger_converted.yaml" }, { "code": "owasp-define-error-responses-500", "path": [ "paths", "/profile", "get", "responses", "500" ], "message": "missing schema for `500` response on `GET`", "severity": 1, "range": { "start": { "line": 22, "character": 11 }, "end": { "line": 22, "character": 18 } }, "source": "swagger_converted.yaml" } ] ```

The diff between v0.6.3 and v0.7.0 shows a lot of rewriting of the OWASP ruleset. There are no test cases for swagger 2 specifications. Has support for swagger 2 been dropped in this ruleset or is it lacking implementation?

daveshanley commented 3 months ago

When I re-built the OWASP rules, they were all written to use the programatic model, instead of using JSON path lookups (which were very slow, prone to breaking and spewed duplicate results).

The programatic model only works with OpenAPI 3+ and not swagger.

I am actually deprecating swagger support across most of the built in functions to be honest. Swagger is old and proprietary and would mean duplicating a huge amount of logic to support it.

So the short answer, expect deteriorating support for swagger and increasing accuracy and power for OpenAPI in vacuum.