Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A malformed JSON body allows missing required properties to validate... #17

Closed
jasonquigleyhpecom opened this issue Aug 3, 2023 · 2 comments · Fixed by #19
Closed

Comments

@jasonquigleyhpecom
Copy link

jasonquigleyhpecom commented Aug 3, 2023

Hello Dave,

when I pass a malformed JSON body, I can trick the validation to pass a document with missing required properties:

Example code:

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)
			}
		}
	}

Schema file:

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

Malformed payload:

{
	"name": "Garbage burger",
	"patties": 3,
}

Result:

Spec file is:    burgers-inline.yaml
Path is:         /burgers/create-burger
Payload file is: burger-malformed.json

Correct payload:

{
	"name": "Garbage burger",
	"patties": 3
}

Result:

Spec file is:    burgers-inline.yaml
Path is:         /burgers/create-burger
Payload file is: burger-missing.json
-------> Reason: missing properties: 'vegetarian', Location: /required
@daveshanley
Copy link
Member

Hmm.. I will look into this for you.

@daveshanley
Copy link
Member

Fixed in v0.0.15. Thank you for making libopenapi better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants