Skip to content

🚨 [security] Update @fastify/middie 8.3.0 → 9.1.0 (major)#587

Open
depfu[bot] wants to merge 1 commit intomainfrom
depfu/update/pnpm/@fastify/middie-9.1.0
Open

🚨 [security] Update @fastify/middie 8.3.0 → 9.1.0 (major)#587
depfu[bot] wants to merge 1 commit intomainfrom
depfu/update/pnpm/@fastify/middie-9.1.0

Conversation

@depfu
Copy link
Contributor

@depfu depfu bot commented Jan 20, 2026


🚨 Your current dependencies have known security vulnerabilities 🚨

This dependency update fixes known security vulnerabilities. Please see the details below and assess their impact carefully. We recommend to merge and deploy this as soon as possible!


Here is everything you need to know about this upgrade. Please take a good look at what changed and the test results before merging this pull request.

What changed?

✳️ @​fastify/middie (8.3.0 → 9.1.0) · Repo

Security Advisories 🚨

🚨 Fastify Middie Middleware Path Bypass

Summary

A security vulnerability exists in @fastify/middie 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.

Details

The vulnerability is caused by how middie matches requests against registered middleware paths.

  1. Regex Generation: When fastify.use('/admin', ...) is called, middie uses path-to-regexp to generate a regular expression for the path /admin.
  2. Request Matching: For every request, middie executes this regular expression against req.url (or req.originalUrl).
  3. The Flaw: req.url in Fastify contains the raw, undecoded path string.
    • The generated regex expects a decoded path (e.g., /admin).
    • If a request is sent to /%61dmin, the regex comparison fails (/^\/admin/ does not match /%61dmin).
    • middie assumes the middleware does not apply and calls next().
  4. Route Execution: The request proceeds to Fastify's internal router, which performs URL decoding. It correctly identifies /%61dmin as /admin and executes the corresponding route handler.

Incriminated Source Code:
In the provided middie source:

// ... inside Holder function
if (regexp) {
  const result = regexp.exec(url) // <--- 'url' is undecoded.
  if (result) {
    // ... executes middleware ...
  } else {
    that.done() // <--- Middleware skipped on mismatch
  }
}

PoC

Step 1: Run the following Fastify application (save as app.js):

const fastify = require('fastify')({ logger: true });

async function start() {
// Register middie for Express-style middleware support
await fastify.register(require('@fastify/middie'));

// Middleware to block /admin route
fastify.use('/admin', (req, res, next) => {
res.statusCode = 403;
res.end('Forbidden: Access to /admin is blocked');
});

// Sample routes
fastify.get('/', async (request, reply) => {
return { message: 'Welcome to the homepage' };
});

fastify.get('/admin', async (request, reply) => {
return { message: 'Admin panel' };
});

// Start server
try {
await fastify.listen({ port: 3008 });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
}

start();

Step 2: Execute the attack.

  1. Normal Request (Blocked):
    curl http://localhost:3008/admin
    # Output: Forbidden: Access to /admin is blocked
  2. Bypass Request (Successful):
    curl http://localhost:3008/%61dmin
    # Output: {"message":"Admin panel"}

Impact

  • Type: Authentication/Authorization Bypass.
  • Affected Components: Applications using @fastify/middie to apply security controls (auth, rate limiting, IP filtering) to specific route prefixes.
  • Severity: High. Attackers can trivially bypass critical security middleware to access protected administrative or sensitive endpoints.
Release Notes

9.1.0

What's Changed

New Contributors

Full Changelog: v9.0.3...v9.1.0

9.0.3

What's Changed

  • build(deps-dev): bump helmet from 7.2.0 to 8.0.0 by @dependabot in #217
  • refactor(lib/engine): replace var with let by @Fdawgs in #218
  • build(deps): bump fastify/workflows from 5.0.0 to 5.0.1 by @dependabot in #219
  • style: remove trailing whitespace by @Fdawgs in #220
  • docs(readme): update ci badge syntax by @Fdawgs in #221
  • build(deps-dev): replace standard with neostandard by @Fdawgs in #222
  • types: use node: prefix for builtins by @Fdawgs in #223
  • build(deps-dev): bump neostandard from 0.11.9 to 0.12.0 by @dependabot in #224
  • build(deps-dev): add eslint, peer dep of neostandard by @Fdawgs in #225
  • refactor: prefix unused params with underscores by @Fdawgs in #226
  • docs(readme): spelling and grammar fixes by @Fdawgs in #227

Full Changelog: v9.0.2...v9.0.3

9.0.2

What's Changed

Full Changelog: v9.0.1...v9.0.2

9.0.1

Security

  • path-to-regexp is updated to 8.1.0 to prevent ReDOS attack, it is recommended to use the latest version of this package.

What's Changed

Full Changelog: v9.0.0...v9.0.1

8.3.3

Security

  • path-to-regexp is updated to 6.3.0 to prevent ReDOS attack, it is recommended to use the latest version of this package.

What's Changed

Full Changelog: v8.3.2...v8.3.3

8.3.2

Deprecated

This version includes too much breaking change due to security patch. Please upgrade to version 8.3.3 which includes the security patch with minimal breakages.

Security

  • path-to-regexp is updated to 8.1.0 to prevent ReDOS attack, it is recommended to use the latest version of this package.

You may see some unexpected breaking due the security patch. Here is the workaround,

  1. when you are using wildcard *, you must to provides a param name.
// before
fastify.use('*.css')
// after
fastify.use('*filename{.css}')

What's Changed

Full Changelog: v8.3.1...v8.3.2

8.3.1

What's Changed

  • build(deps-dev): bump tsd from 0.28.1 to 0.29.0 by @dependabot in #189
  • perf: use node: prefix to bypass require.cache call for builtins by @Fdawgs in #190
  • chore: add .gitattributes file by @Fdawgs in #192
  • chore(package): explicitly declare js module type by @Fdawgs in #193
  • build(deps-dev): bump tsd from 0.29.0 to 0.30.0 by @dependabot in #194
  • docs(readme): replace fastify.io links with fastify.dev by @Fdawgs in #195
  • docs(readme): remove www. from fastify.dev urls by @Fdawgs in #196
  • chore(.gitignore): add .tap/ dir by @Fdawgs in #197
  • build(deps-dev): bump tsd from 0.30.7 to 0.31.0 by @dependabot in #198
  • Warn for possible ReDoS by @mcollina in #200
  • Only sets req.raw.body if body defined, aligning behaviour with node:http by @didley in #201

New Contributors

Full Changelog: v8.3.0...v8.3.1

Does any of this look wrong? Please let us know.

Commits

See the full diff on Github. The new version differs by 58 commits:


Depfu Status

Depfu will automatically keep this PR conflict-free, as long as you don't add any commits to this branch yourself. You can also trigger a rebase manually by commenting with @depfu rebase.

All Depfu comment commands
@​depfu rebase
Rebases against your default branch and redoes this update
@​depfu recreate
Recreates this PR, overwriting any edits that you've made to it
@​depfu merge
Merges this PR once your tests are passing and conflicts are resolved
@​depfu cancel merge
Cancels automatic merging of this PR
@​depfu close
Closes this PR and deletes the branch
@​depfu reopen
Restores the branch and reopens this PR (if it's closed)
@​depfu pause
Ignores all future updates for this dependency and closes this PR
@​depfu pause [minor|major]
Ignores all future minor/major updates for this dependency and closes this PR
@​depfu resume
Future versions of this dependency will create PRs again (leaves this PR as is)

@depfu depfu bot added the depfu label Jan 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants