when I pass a malformed JSON body, I can trick the validation to pass a document with missing required
properties:
package main
import (
"bytes"
"flag"
"fmt"
"net/http"
"os"
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi-validator/requests"
"github.com/pb33f/libopenapi/datamodel"
)
func main() {
var path, payload, specFile string
flag.StringVar(&path, "path",
"/burgers/create-burger",
"request path",
)
flag.StringVar(&payload, "payload",
"burger-with-garbage.json",
"payload file",
)
flag.StringVar(&specFile, "spec",
"burgers-inline.yaml",
"spec file",
)
flag.Parse()
fmt.Println("Spec file is: " + specFile)
fmt.Println("Path is: " + path)
fmt.Println("Payload file is: " + payload)
// Load an OpenAPI Spec file
specBytes, err := os.ReadFile(specFile)
if err != nil {
panic(err)
}
// Load the payload file
payloadBytes, err := os.ReadFile(payload)
if err != nil {
panic(err)
}
// Enable file references
config := datamodel.DocumentConfiguration{
AllowFileReferences: true,
}
// Create a new OpenAPI document using libopenapi
document, docErrs := libopenapi.NewDocumentWithConfiguration(specBytes, &config)
if docErrs != nil {
panic(docErrs)
}
// Build a model
document.SetConfiguration(&datamodel.DocumentConfiguration{AllowFileReferences: true})
docModel, errors := document.BuildV3Model()
if len(errors) > 0 {
for i := range errors {
fmt.Printf("error: %e\n", errors[i])
}
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
}
request, err := http.NewRequest(http.MethodPost, "http://localhost"+path, bytes.NewReader(payloadBytes))
if err != nil {
panic(err)
}
request.Header.Set("Content-Type", "application/json")
valdtr := requests.NewRequestBodyValidator(&docModel.Model)
valid, valdtrErrors := valdtr.ValidateRequestBody(request)
if !valid {
for _, err := range valdtrErrors {
for _, reason := range err.SchemaValidationErrors {
fmt.Printf("-------> %+v\n", reason)
}
}
}
openapi: 3.1.0
info:
title: Burgers
license:
name: License Agreement
url: https://www.example.com/licensing.html
version: latest
description: |
More burgers!
A unified API for consuming burgers
contact:
name: Ronald Macdonald
email: [email protected]
servers:
- url: https://api.example.com
description: Development environment
externalDocs:
description: Find out more about burgers
url: https://www.example.com
security:
- Bearer: []
paths:
/burgers/create-burger:
post:
operationId: createBurger
requestBody:
content:
application/json:
schema:
type: object
required:
- name
- patties
- vegetarian
properties:
name:
type: string
patties:
type: integer
vegetarian:
type: boolean
unevaluatedProperties: false
examples:
pbjBurger:
summary: A horrible, nutty, sticky mess.
value:
name: Peanut And Jelly
patties: 3
vegetarian: true
responses:
'201':
description: Burger created
headers:
Location:
description: URL for the created burger
schema:
type: string
format: uri
example: burgers/0e7f516c-0829-4135-83d6-09ce844ddd9d
components:
securitySchemes:
Bearer:
description: Uses a token for authorization
type: http
scheme: bearer
{
"name": "Garbage burger",
"patties": 3,
}
Spec file is: burgers-inline.yaml
Path is: /burgers/create-burger
Payload file is: burger-malformed.json
{
"name": "Garbage burger",
"patties": 3
}
Spec file is: burgers-inline.yaml
Path is: /burgers/create-burger
Payload file is: burger-missing.json
-------> Reason: missing properties: 'vegetarian', Location: /required