{"id":16927478,"url":"https://github.com/dubzzz/fuzz-rest-api","last_synced_at":"2025-03-22T11:31:08.886Z","repository":{"id":54287891,"uuid":"130416259","full_name":"dubzzz/fuzz-rest-api","owner":"dubzzz","description":"Derive property based testing fast-check into a fuzzer for REST APIs","archived":false,"fork":false,"pushed_at":"2021-02-26T10:04:44.000Z","size":65,"stargazers_count":39,"open_issues_count":1,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-18T10:51:35.900Z","etag":null,"topics":["fast-check","fuzzing","property-based-testing","quickcheck","rest-api"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dubzzz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-20T21:38:32.000Z","updated_at":"2025-01-08T10:00:11.000Z","dependencies_parsed_at":"2022-08-13T11:01:01.983Z","dependency_job_id":null,"html_url":"https://github.com/dubzzz/fuzz-rest-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dubzzz%2Ffuzz-rest-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dubzzz%2Ffuzz-rest-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dubzzz%2Ffuzz-rest-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dubzzz%2Ffuzz-rest-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dubzzz","download_url":"https://codeload.github.com/dubzzz/fuzz-rest-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244951307,"owners_count":20537358,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fast-check","fuzzing","property-based-testing","quickcheck","rest-api"],"created_at":"2024-10-13T20:34:20.211Z","updated_at":"2025-03-22T11:31:08.419Z","avatar_url":"https://github.com/dubzzz.png","language":"JavaScript","readme":"Wikipedia defines Fuzzing as:\n\n\u003e Fuzzing or fuzz testing is an automated software testing technique that involves providing invalid, unexpected, or random data as inputs to a computer program.\n\u003e The program is then monitored for exceptions such as crashes, or failing built-in code assertions or for finding potential memory leaks.\n\nThis repository derives a property based testing framework called [fast-check](https://github.com/dubzzz/fast-check/) into a fuzzing system.\n\n## Steps to run this code locally:\n\n```sh\ngit clone https://github.com/dubzzz/fuzz-rest-api.git\ncd fuzz-rest-api\nnpm install\nnpm run start #launch a webserver on port 8080\nnpm run test  #run the 'fuzzing'\n```\n\nIt intentially comes with an unsafe implementation of its APIs.\n\n- /api/login - does not escape incoming parameters from POST\n- /api/profile/:uid - considers uid to be an integer while its not\n\n## How does it work?\n\nThis Proof-Of-Concept uses the power of property based testing to generate inputs for a REST end-point.\nIt sends the generated values to this end-point and check for the property - _whatever the data I send I should not receive an Internal Error aka 500_.\n\nBasically defining the REST inputs using [fast-check](https://github.com/dubzzz/fast-check/) is quite simple:\n```js\nfc.record({\n  nameOfFieldOne: fc.string(),\n  nameOfFieldTwo: fc.string(),\n  nameOfFieldThree: fc.string(),\n  //...\n  nameOfFieldWithMoreComplexLayout: fc.record({\n    subFieldOne: fc.string(),\n    //...\n  })\n})\n```\n\nIn the above example `nameOfFieldOne`, `nameOfFieldTwo`... are all filled with string values. Depending on your API you may want to be more precise on the types you are using. For instance if `nameOfFieldOne` expects integers you might prefer `fc.integer()`. The benefit of specifying the real types is that you may find bugs deaper in your code.\n\nNonetheless the two approches are fully complementary. Depending on the type safety provided by your back, you may want to check that sending other types will not cause Internal Server Errors like here in `/api/profile/:uid` route.\n\nOne solution to have the better of those two worlds is to use `fc.oneof(/*realType, eg.: fc.integer()*/, fc.string())` everywhere you want to specify real type.\n\nYou may also use the helper https://github.com/dubzzz/fuzz-rest-api/blob/master/test/inferPayloadArbitrary.js in order to automatically build the arbitrary from a given payload. With this helper, input `{min: 9, max: 30, label: 'toto'}` will produce the arbitrary `fc.record({min: fc.integer(), max: fc.integer(), label: fc.string()})` or the alternative with `fc.oneof(...)`.\n\n## Output of test command\n\n`npm run test` produces the following output:\n\n```\n$ npm run test\n\n\u003e poc-fuzz-rest-api@1.0.0 test ...\n\u003e mocha --require babel-polyfill --require babel-register \"test/**/*.js\"\n\n\n\n  Fuzzing REST API\n    1) /api/login\n    2) /api/profile/:uid\n    3) /api/comment\n\n\n  0 passing (452ms)\n  3 failing\n\n  1) Fuzzing REST API\n       /api/login:\n     Error: Property failed after 5 tests (seed: 1524328189654, path: 4:0:0:1:0:4): [{\"password\":\"'\"}]\nShrunk 5 time(s)\nGot error: Error: Internal Server Error, got: {\"data\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n\u003cmeta charset=\\\"utf-8\\\"\u003e\\n\u003ctitle\u003eError\u003c/title\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n\u003cpre\u003eError: SQLITE_ERROR: unrecognized token: \u0026quot;\u0026#39;\u0026#39;\u0026#39;\u0026quot;\u003c/pre\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"status\":500}\n\nStack trace: Error: Internal Server Error, got: {\"data\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n\u003cmeta charset=\\\"utf-8\\\"\u003e\\n\u003ctitle\u003eError\u003c/title\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n\u003cpre\u003eError: SQLITE_ERROR: unrecognized token: \u0026quot;\u0026#39;\u0026#39;\u0026#39;\u0026quot;\u003c/pre\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"status\":500}\n    at exports.throwIfHttpFailed (test/asyncHttp.js:38:33)\n    at \u003canonymous\u003e\n    at process._tickCallback (internal/process/next_tick.js:188:7)\n      at throwIfFailed (node_modules\\fast-check\\src\\check\\runner\\utils\\utils.ts:146:11)\n      at \u003canonymous\u003e\n      at process._tickCallback (internal/process/next_tick.js:188:7)\n\n  2) Fuzzing REST API\n       /api/profile/:uid:\n     Error: Property failed after 1 tests (seed: 1524328189825, path: 0:1:0:0:0): [\"\\u0000\"]\nShrunk 4 time(s)\nGot error: Error: Internal Server Error, got: {\"data\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n\u003cmeta charset=\\\"utf-8\\\"\u003e\\n\u003ctitle\u003eError\u003c/title\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n\u003cpre\u003eError: SQLITE_ERROR: near \u0026quot;=\u0026quot;: syntax error\u003c/pre\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"status\":500}\n\nStack trace: Error: Internal Server Error, got: {\"data\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n\u003cmeta charset=\\\"utf-8\\\"\u003e\\n\u003ctitle\u003eError\u003c/title\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n\u003cpre\u003eError: SQLITE_ERROR: near \u0026quot;=\u0026quot;: syntax error\u003c/pre\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"status\":500}\n    at exports.throwIfHttpFailed (test/asyncHttp.js:38:33)\n    at \u003canonymous\u003e\n    at process._tickCallback (internal/process/next_tick.js:188:7)\n      at throwIfFailed (node_modules\\fast-check\\src\\check\\runner\\utils\\utils.ts:146:11)\n      at \u003canonymous\u003e\n      at process._tickCallback (internal/process/next_tick.js:188:7)\n\n  3) Fuzzing REST API\n       /api/comment:\n     Error: Property failed after 17 tests (seed: 1524328189856, path: 16:0:2:3:4:4:4:4): [{\"user\":{\"login\":\"\"},\"comment\":{\"postId\":0,\"commentId\":\"\"}}]\nShrunk 7 time(s)\nGot error: Error: Internal Server Error, got: {\"data\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n\u003cmeta charset=\\\"utf-8\\\"\u003e\\n\u003ctitle\u003eError\u003c/title\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n\u003cpre\u003eError: Supposed it failed on this case\u003cbr\u003e \u0026nbsp; \u0026nbsp;at router.post.wrap (src/server.js:62:61)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at node_modules/async-middleware/dist/index.js:18:23\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at next (node_modules/express/lib/router/route.js:137:13)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Route.dispatch (node_modules/express/lib/router/route.js:112:3)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at node_modules/express/lib/router/index.js:281:22\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Function.process_params (node_modules/express/lib/router/index.js:335:12)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at next (node_modules/express/lib/router/index.js:275:10)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Function.handle (node_modules/express/lib/router/index.js:174:3)\u003c/pre\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"status\":500}\n\nStack trace: Error: Internal Server Error, got: {\"data\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\u003chead\u003e\\n\u003cmeta charset=\\\"utf-8\\\"\u003e\\n\u003ctitle\u003eError\u003c/title\u003e\\n\u003c/head\u003e\\n\u003cbody\u003e\\n\u003cpre\u003eError: Supposed it failed on this case\u003cbr\u003e \u0026nbsp; \u0026nbsp;at router.post.wrap (src/server.js:62:61)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at node_modules/async-middleware/dist/index.js:18:23\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at next (node_modules/express/lib/router/route.js:137:13)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Route.dispatch (node_modules/express/lib/router/route.js:112:3)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at node_modules/express/lib/router/index.js:281:22\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Function.process_params (node_modules/express/lib/router/index.js:335:12)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at next (node_modules/express/lib/router/index.js:275:10)\u003cbr\u003e \u0026nbsp; \u0026nbsp;at Function.handle (node_modules/express/lib/router/index.js:174:3)\u003c/pre\u003e\\n\u003c/body\u003e\\n\u003c/html\u003e\\n\",\"status\":500}\n    at exports.throwIfHttpFailed (test/asyncHttp.js:38:33)\n    at \u003canonymous\u003e\n    at process._tickCallback (internal/process/next_tick.js:188:7)\n      at throwIfFailed (node_modules\\fast-check\\src\\check\\runner\\utils\\utils.ts:146:11)\n      at \u003canonymous\u003e\n      at process._tickCallback (internal/process/next_tick.js:188:7)\n```\n\nIt detects:\n- sql injection in /api/login with counterexample: `{\"password\":\"'\"}`\n- sql injection in /api/profile/:uid with :uid: `\\u0000`\n- implementation problem in /api/comment with counterexample: `{\"user\":{\"login\":\"\"},\"comment\":{\"postId\":0,\"commentId\":\"\"}}`\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdubzzz%2Ffuzz-rest-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdubzzz%2Ffuzz-rest-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdubzzz%2Ffuzz-rest-api/lists"}