Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,21 @@ class RouteHandlerLimitedByRateLimiterFlexible extends RateLimitingMiddleware in
private class FastifyRateLimiter extends RateLimitingMiddleware {
FastifyRateLimiter() { this = DataFlow::moduleImport("fastify-rate-limit") }
}

/**
* An options object with a `rateLimit` config passed to a Fastify shorthand route method,
* such as `fastify.post('/path', { config: { rateLimit: { ... } } }, handler)`.
Comment on lines +196 to +197
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment describes only the config.rateLimit form, but the implementation also treats a top-level rateLimit property in the options object as per-route rate limiting. Consider updating the doc comment to mention both supported shapes so the documentation matches the behavior.

Suggested change
* An options object with a `rateLimit` config passed to a Fastify shorthand route method,
* such as `fastify.post('/path', { config: { rateLimit: { ... } } }, handler)`.
* An options object passed to a Fastify shorthand route method that enables per-route
* rate limiting, either via `config.rateLimit` or via a top-level `rateLimit` property,
* such as `fastify.post('/path', { config: { rateLimit: { ... } } }, handler)` or
* `fastify.post('/path', { rateLimit: { ... } }, handler)`.

Copilot uses AI. Check for mistakes.
*/
private class FastifyPerRouteRateLimit extends RateLimitingMiddleware {
FastifyPerRouteRateLimit() {
exists(Fastify::RouteSetup setup |
not setup.getMethodName() = ["route", "addHook"] and
setup.getNumArgument() >= 3 and
this.flowsTo(setup.getArgument(1))
|
exists(this.getAPropertySource("config").getAPropertySource("rateLimit"))
or
exists(this.getAPropertySource("rateLimit"))
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* The query `js/missing-rate-limiting` now takes Fastify per-route
rate limiting into account.
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
| tst.js:64:25:64:63 | functio ... req); } | This route handler performs $@, but is not rate-limited. | tst.js:64:46:64:60 | verifyUser(req) | authorization |
| tst.js:76:25:76:53 | catchAs ... ndler1) | This route handler performs $@, but is not rate-limited. | tst.js:14:40:14:46 | login() | authorization |
| tst.js:88:24:88:40 | expensiveHandler1 | This route handler performs $@, but is not rate-limited. | tst.js:14:40:14:46 | login() | authorization |
| tst.js:112:28:112:44 | expensiveHandler1 | This route handler performs $@, but is not rate-limited. | tst.js:14:40:14:46 | login() | authorization |
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,25 @@ const fastifyApp = require('fastify')();
fastifyApp.get('/foo', expensiveHandler1); // $ Alert
fastifyApp.register(require('fastify-rate-limit'));
fastifyApp.get('/bar', expensiveHandler1);

// Fastify per-route rate limiting via config.rateLimit
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section header mentions only config.rateLimit, but the following test cases also cover the { rateLimit: ... } options shape. Consider adjusting the comment to reflect both forms to avoid confusion when updating/reading the tests later.

Suggested change
// Fastify per-route rate limiting via config.rateLimit
// Fastify per-route rate limiting via config.rateLimit or direct { rateLimit: ... } options

Copilot uses AI. Check for mistakes.
const fastifyApp2 = require('fastify')();
fastifyApp2.register(require('@fastify/rate-limit'));

fastifyApp2.post('/login', {
config: {
rateLimit: {
max: 3,
timeWindow: '1 minute'
}
}
}, expensiveHandler1); // OK - has per-route rateLimit config

fastifyApp2.post('/signup', {
rateLimit: {
max: 5,
timeWindow: '1 minute'
}
}, expensiveHandler1); // OK - has per-route rateLimit directly in options

fastifyApp2.post('/other', expensiveHandler1); // $ Alert - no rate limiting
Loading