Yelp / fuzz-lightyear

A pytest-inspired, DAST framework, capable of identifying vulnerabilities in a distributed, micro-service ecosystem through chaos engineering testing and stateful, Swagger fuzzing.
Other
205 stars 25 forks source link

copy parameter definition to avoid mutating bravado internals #15

Closed acoover closed 4 years ago

acoover commented 4 years ago

A valid swagger spec with a body parameter where the required field is provided will have that field over-written with a boolean due to the mutation of the parameter by the request.py module. Instead, we should copy the parameter dictionary to avoid mutating the field.

Example swagger spec

{
   "basePath": "/",
   "swagger": "2.0",
   "consumes": [
      "application/json"
   ],
   "produces": [
      "application/json"
   ],
   "schemes": [
      "http"
   ],
   "info": {
      "title": "Foo API",
      "description": "API description in Markdown.",
      "version": "1.0.0"
   },
   "paths": {
      "/foo/": {
         "post": {
            "operationId": "foo",
            "parameters": [
               {
                  "name": "body",
                  "in": "body",
                  "required": true,
                  "schema": {
                     "type": "object",
                     "properties": {
                        "foo": {
                           "description": "Foo",
                           "type": "integer"
                        }
                     },
                     "required": [
                        "foo"
                     ]
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "OK"
               }
            }
         }
      }
   }
}

Example traceback

Traceback (most recent call last):
  File "/nail/home/acoover/pg/fuzz_lightyear_core/fuzz_lightyear/main.py", line 106, in run_tests
    run_sequence(result.requests, result.responses)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/fuzz_lightyear/runner.py", line 13, in run_sequence
    response = request.send()
  File "/nail/home/acoover/pg/fuzz_lightyear_core/fuzz_lightyear/request.py", line 146, in send
    **kwargs
  File "/nail/home/acoover/pg/fuzz_lightyear_core/fuzz_lightyear/supplements/abstraction.py", line 57, in default_request_method
    )(*args, **kwargs)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado/client.py", line 247, in __call__
    self.operation, request_options, **op_kwargs)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado/client.py", line 285, in construct_request
    construct_params(operation, request, op_kwargs)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado/client.py", line 308, in construct_params
    marshal_param(param, param_value, request)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado_core/param.py", line 121, in marshal_param
    value = marshal_schema_object(swagger_spec, param_spec, value)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado_core/marshal.py", line 52, in marshal_schema_object
    marshaling_method = _get_marshaling_method(swagger_spec=swagger_spec, object_schema=schema_object_spec)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado_core/_decorators.py", line 81, in wrapper
    return func(*args, **kwargs)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado_core/util.py", line 118, in wrapper
    cached_value = func(*args, **kwargs)
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado_core/marshal.py", line 177, in _get_marshaling_method
    return null_decorator(_marshaling_method_object(swagger_spec, object_schema))
  File "/nail/home/acoover/pg/fuzz_lightyear_core/venv/lib/python3.6/site-packages/bravado_core/marshal.py", line 338, in _marshaling_method_object
    required_properties = set(object_schema.get('required', []))
TypeError: 'bool' object is not iterable