openapi-fuzzer-core
Advanced tools
Comparing version 1.0.1 to 1.0.2
{ | ||
"name": "openapi-fuzzer-core", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "A library to generate random requests based on open-api specifications.", | ||
@@ -28,3 +28,6 @@ "main": "./src/index.js", | ||
"uvu": "^0.4.1" | ||
}, | ||
"dependencies": { | ||
"klona": "^2.0.4" | ||
} | ||
} |
@@ -8,7 +8,7 @@ const Swagger = require('./swagger'); | ||
fuzzes.fuzz(); | ||
return fuzzes.requests; | ||
return fuzzes.specs; | ||
} | ||
} | ||
}; | ||
module.exports = fuzz; |
@@ -0,1 +1,3 @@ | ||
const { klona } = require("klona"); | ||
const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete']; | ||
@@ -8,17 +10,55 @@ | ||
this.basePath = data.basePath; | ||
this.requests = []; | ||
this.specs = []; | ||
} | ||
fuzz() { | ||
this.fuzzPathMethods(); | ||
this.fuzzPaths(); | ||
this.fuzzMethods(); | ||
this.fuzzParams(); | ||
} | ||
fuzzPathMethods() { | ||
fuzzPaths() { | ||
HTTP_METHODS.forEach(method => { | ||
this.specs.push({ | ||
name: 'PATH', | ||
request: { | ||
method, | ||
path: '/ROOT/INVALID/PATH' | ||
}, | ||
expect: { | ||
status: [404] | ||
} | ||
}); | ||
}); | ||
for (const route of Object.keys(this.data.paths)) { | ||
const path = this.data.paths[route]; | ||
for (const method of Object.keys(path)) { | ||
this.specs.push({ | ||
name: 'PATH', | ||
request: { | ||
method, | ||
path: `${this.basePath}${route}/INVALID/PATH` | ||
}, | ||
expect: { | ||
status: [404] | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
fuzzMethods() { | ||
for (const route of Object.keys(this.data.paths)) { | ||
const path = this.data.paths[route]; | ||
HTTP_METHODS.forEach(method => { | ||
if (!path[method]) { | ||
this.requests.push({ | ||
method, | ||
path: `${this.basePath}${route}` | ||
this.specs.push({ | ||
name: 'METHOD', | ||
request: { | ||
method, | ||
path: `${this.basePath}${route}` | ||
}, | ||
expect: { | ||
status: [405] | ||
} | ||
}); | ||
@@ -30,4 +70,223 @@ } | ||
fuzzParams() { | ||
for (const route of Object.keys(this.data.paths)) { | ||
const path = this.data.paths[route]; | ||
for (const method of Object.keys(path)) { | ||
const info = path[method]; | ||
const parameters = info.parameters; | ||
if (parameters && parameters.length > 0) { | ||
this.fuzzPathParams(route, method, parameters); | ||
this.fuzzQueryParams(route, method, parameters); | ||
this.fuzzBodyParams(route, method, parameters); | ||
} | ||
} | ||
} | ||
} | ||
fuzzPathParams(route, method, parameters) { | ||
const pathParameters = parameters.filter(parameter => parameter.in === 'path'); | ||
const fakePathParams = this.getFakeParams(pathParameters); | ||
for (const parameter of pathParameters) { | ||
const values = this.fuzzParameter(parameter); | ||
for (const value of values) { | ||
const pathParams = Object.assign({}, fakePathParams); | ||
pathParams[`${parameter.name}`] = value; | ||
this.specs.push({ | ||
name: 'PATH PARAMS', | ||
request: { | ||
method, | ||
path: `${this.basePath}${route}`, | ||
pathParams | ||
}, | ||
expect: { | ||
status: [400] | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
fuzzQueryParams(route, method, parameters) { | ||
const pathParameters = parameters.filter(parameter => parameter.in === 'path'); | ||
const pathParams = this.getFakeParams(pathParameters); | ||
const queryParameters = parameters.filter(parameter => parameter.in === 'query'); | ||
const previousQueryParams = {}; | ||
for (const parameter of queryParameters) { | ||
const values = this.fuzzParameter(parameter); | ||
for (const value of values) { | ||
const queryParams = Object.assign({}, previousQueryParams); | ||
queryParams[`${parameter.name}`] = value; | ||
this.specs.push({ | ||
name: 'QUERY PARAMS', | ||
request: { | ||
method, | ||
path: `${this.basePath}${route}`, | ||
queryParams, | ||
pathParams | ||
}, | ||
expect: { | ||
status: [400] | ||
} | ||
}); | ||
} | ||
previousQueryParams[`${parameter.name}`] = this.fakeParameter(parameter); | ||
} | ||
} | ||
fuzzBodyParams(route, method, parameters) { | ||
const pathParameters = parameters.filter(parameter => parameter.in === 'path'); | ||
const pathParams = this.getFakeParams(pathParameters); | ||
const queryParameters = parameters.filter(parameter => parameter.in === 'query'); | ||
const queryParams = this.getFakeParams(queryParameters); | ||
const bodyParameters = parameters.filter(parameter => parameter.in === 'body'); | ||
for (const parameter of bodyParameters) { | ||
const schema = parameter.schema; | ||
if (schema && schema['$ref']) { | ||
const values = this.fuzzParameter(this.getDefinition(schema['$ref']), true); | ||
for (const value of values) { | ||
this.specs.push({ | ||
name: 'BODY', | ||
request: { | ||
method, | ||
path: `${this.basePath}${route}`, | ||
queryParams, | ||
pathParams, | ||
body: value | ||
}, | ||
expect: { | ||
status: [400] | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
fuzzParameter(parameter, nonPrimitives) { | ||
switch (parameter.type) { | ||
case 'integer': | ||
return this.fuzzIntegerParam(parameter, nonPrimitives); | ||
case 'string': | ||
return this.fuzzStringParam(parameter, nonPrimitives); | ||
case 'boolean': | ||
return this.fuzzBooleanParam(parameter, nonPrimitives); | ||
case 'object': | ||
return this.fuzzObjectParam(parameter, nonPrimitives); | ||
case 'array': | ||
return this.fuzzArrayParam(parameter, nonPrimitives); | ||
default: | ||
if (parameter['$ref']) { | ||
return this.fuzzParameter(this.getDefinition(parameter['$ref']), nonPrimitives); | ||
} | ||
return []; | ||
} | ||
} | ||
fuzzIntegerParam(parameter, nonPrimitives) { | ||
const values = ['STRING', true]; | ||
if (typeof parameter.minimum === 'number') { | ||
values.push(parameter.minimum - 1); | ||
} | ||
if (typeof parameter.maximum === 'number') { | ||
values.push(parameter.maximum + 1); | ||
} | ||
if (nonPrimitives) { | ||
return values.concat([{}, null, []]); | ||
} | ||
return values; | ||
} | ||
fuzzStringParam(parameter, nonPrimitives) { | ||
if (nonPrimitives) { | ||
return [10, true, {}, null, []]; | ||
} | ||
return [10]; | ||
} | ||
fuzzBooleanParam(parameter, nonPrimitives) { | ||
if (nonPrimitives) { | ||
return ['STRING', 10, {}, null, []]; | ||
} | ||
return ['STRING', 10]; | ||
} | ||
fuzzObjectParam(parameter, nonPrimitives) { | ||
const values = ['', 'STRING', 10, true, null, []]; | ||
const { required, properties } = parameter; | ||
if (required && required.length > 0) { | ||
values.push({}); | ||
for (const req of required) { | ||
const otherRequiredParams = required.filter(_req => _req !== req); | ||
const value = {}; | ||
for (const otherReqParam of otherRequiredParams) { | ||
value[otherReqParam] = this.fakeParameter(properties[otherReqParam]); | ||
} | ||
values.push(value); | ||
} | ||
} | ||
const goldenCopy = this.fakeParameter(parameter); | ||
for (const property of Object.keys(properties)) { | ||
const fuzzValues = this.fuzzParameter(properties[property], nonPrimitives); | ||
for (const fuzzValue of fuzzValues) { | ||
const fake = klona(goldenCopy); | ||
fake[property] = fuzzValue; | ||
values.push(fake); | ||
} | ||
} | ||
return values; | ||
} | ||
fuzzArrayParam(parameter, nonPrimitives) { | ||
const values = ['', 'STRING', 10, true, null, {}]; | ||
const fzs = this.fuzzParameter(parameter.items, nonPrimitives); | ||
fzs.forEach(fuzz => values.push([fuzz])); | ||
return values; | ||
} | ||
fakeParameter(parameter) { | ||
let fake; | ||
const properties = parameter.properties; | ||
switch (parameter.type) { | ||
case 'integer': | ||
return 10; | ||
case 'string': | ||
if (parameter.example) return parameter.example; | ||
if (parameter.enum) return parameter.enum[0]; | ||
if (parameter.name) return parameter.name; | ||
return 'STRING'; | ||
case 'boolean': | ||
return true; | ||
case 'object': | ||
fake = {}; | ||
for (const property of Object.keys(properties)) { | ||
fake[property] = this.fakeParameter(properties[property]); | ||
} | ||
return fake; | ||
case 'array': | ||
fake = []; | ||
fake.push(this.fakeParameter(parameter.items)); | ||
return fake; | ||
default: | ||
if (parameter['$ref']) { | ||
return this.fakeParameter(this.getDefinition(parameter['$ref'])); | ||
} | ||
return ''; | ||
} | ||
} | ||
getFakeParams(parameters) { | ||
const pathParams = {}; | ||
for (const parameter of parameters) { | ||
pathParams[`${parameter.name}`] = this.fakeParameter(parameter); | ||
} | ||
return pathParams; | ||
} | ||
getDefinition(ref) { | ||
const definition = ref.replace('#/definitions/', ''); | ||
return this.data.definitions[definition]; | ||
} | ||
} | ||
module.exports = Swagger; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
10768
276
1
1
+ Addedklona@^2.0.4
+ Addedklona@2.0.6(transitive)