VYPR
Moderate severityNVD Advisory· Published Jan 8, 2024· Updated Jun 3, 2025

@fastify-reply-from JSON Content-Type parsing confusion

CVE-2023-51701

Description

fastify-reply-from is a Fastify plugin to forward the current HTTP request to another server. A reverse proxy server built with @fastify/reply-from could misinterpret the incoming body by passing an header ContentType: application/json ; charset=utf-8. This can lead to bypass of security checks. This vulnerability has been patched in '@fastify/reply-from` version 9.6.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@fastify/reply-fromnpm
< 9.6.09.6.0

Affected products

1

Patches

1
cbd7c17c09e6

Merge pull request from GHSA-v2v2-hph8-q5xp

https://github.com/fastify/fastify-reply-fromMatteo CollinaJan 8, 2024via ghsa
3 files changed · +56 9
  • index.js+8 9 modified
    @@ -3,6 +3,7 @@
     const fp = require('fastify-plugin')
     const { lru } = require('tiny-lru')
     const querystring = require('fast-querystring')
    +const fastContentTypeParse = require('fast-content-type-parse')
     const Stream = require('node:stream')
     const buildRequest = require('./lib/request')
     const {
    @@ -107,15 +108,13 @@ const fastifyReplyFrom = fp(function from (fastify, opts, next) {
             body = this.request.body
           } else {
             // Per RFC 7231 §3.1.1.5 if this header is not present we MAY assume application/octet-stream
    -        const contentType = req.headers['content-type'] || 'application/octet-stream'
    -        // detect if body should be encoded as JSON
    -        // supporting extended content-type header formats:
    -        // - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
    -        const lowerCaseContentType = contentType.toLowerCase()
    -        const plainContentType = lowerCaseContentType.indexOf(';') > -1
    -          ? lowerCaseContentType.slice(0, lowerCaseContentType.indexOf(';'))
    -          : lowerCaseContentType
    -        const shouldEncodeJSON = contentTypesToEncode.has(plainContentType)
    +        let contentType = 'application/octet-stream'
    +        if (req.headers['content-type']) {
    +          const plainContentType = fastContentTypeParse.parse(req.headers['content-type'])
    +          contentType = plainContentType.type
    +        }
    +
    +        const shouldEncodeJSON = contentTypesToEncode.has(contentType)
             // transparently support JSON encoding
             body = shouldEncodeJSON ? JSON.stringify(this.request.body) : this.request.body
             // update origin request headers after encoding
    
  • package.json+1 0 modified
    @@ -53,6 +53,7 @@
       "dependencies": {
         "@fastify/error": "^3.0.0",
         "end-of-stream": "^1.4.4",
    +    "fast-content-type-parse": "^1.1.0",
         "fast-querystring": "^1.0.0",
         "fastify-plugin": "^4.0.0",
         "pump": "^3.0.0",
    
  • test/fix-GHSA-v2v2-hph8-q5xp.test.js+47 0 added
    @@ -0,0 +1,47 @@
    +'use strict'
    +
    +const t = require('tap')
    +const fastify = require('fastify')
    +const get = require('simple-get').concat
    +const From = require('..')
    +
    +const upstream = fastify()
    +t.teardown(upstream.close.bind(upstream))
    +t.plan(4)
    +
    +upstream.post('/test', async (request, reply) => {
    +  if (typeof request.body === 'object') {
    +    return 'not ok'
    +  }
    +  return 'ok'
    +})
    +
    +upstream.listen({ port: 0 }, function (err) {
    +  t.error(err)
    +
    +  const app = fastify()
    +  app.register(From)
    +  t.teardown(app.close.bind(app))
    +
    +  app.post('/test', (request, reply) => {
    +    if (request.body.method === 'invalid_method') {
    +      return reply.code(400).send({ message: 'payload contains invalid method' })
    +    }
    +    reply.from(`http://127.0.0.1:${upstream.server.address().port}/test`)
    +  })
    +
    +  app.listen({ port: 0 }, function (err) {
    +    t.error(err)
    +
    +    get({
    +      url: `http://127.0.0.1:${app.server.address().port}/test`,
    +      headers: { 'content-type': 'application/json ; charset=utf-8' },
    +      // eslint-disable-next-line no-useless-escape
    +      body: '"{\\\"method\\\":\\\"invalid_method\\\"}"',
    +      method: 'POST'
    +    }, (err, res, data) => {
    +      t.error(err)
    +      t.equal(data.toString(), 'ok')
    +    })
    +  })
    +})
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.