2 examples

Missing rate limiting

Request frequency limits missing, risking overload or abuse.

[ FAQ1 ]

What is missing rate limiting?

Missing rate limiting means an application or API doesn't enforce limits on the number of requests clients can make within a specific timeframe. Without proper rate limiting, an API can be overwhelmed by high-frequency or malicious requests, potentially causing degraded performance, resource exhaustion, or denial-of-service (DDoS) conditions. Attackers may exploit this vulnerability to exhaust server resources, compromise system stability, or gain unauthorized advantage. Implementing rate limiting is essential for maintaining API security, reliability, and performance.
[ FAQ2 ]

How to implement rate limiting

To implement rate limiting, set clear policies defining the maximum allowable requests per user or IP address within a given time window. Use middleware or API gateways that automatically enforce these limits and return appropriate HTTP status codes, such as 429 Too Many Requests, when thresholds are exceeded. Utilize robust libraries or frameworks specifically designed for request throttling and integrate them seamlessly into your application or API stack. Consider additional security layers like Web Application Firewalls (WAF) or cloud-based services providing DDoS protection. Regularly monitor API traffic and adjust limits dynamically to maintain optimal balance between security and usability.
diff block
+import { z } from "zod";
+
+import { MicrosoftTeamsIntegrationsSchema, WorkflowIntegrationsSchema } from "@app/db/schemas";
+import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
+import { slugSchema } from "@app/server/lib/schemas";
+import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
+import { AuthMode } from "@app/services/auth/auth-type";
+import { WorkflowIntegrationStatus } from "@app/services/workflow-integration/workflow-integration-types";
+
+const sanitizedMicrosoftTeamsIntegrationSchema = WorkflowIntegrationsSchema.pick({
+ id: true,
+ description: true,
+ slug: true,
+ integration: true
+}).merge(
+ MicrosoftTeamsIntegrationsSchema.pick({
+ tenantId: true
+ }).extend({
+ status: z.nativeEnum(WorkflowIntegrationStatus)
+ })
+);
+
+export const registerMicrosoftTeamsRouter = async (server: FastifyZodProvider) => {
+ server.route({
+ method: "POST",
+ url: "/",
+ config: {
+ rateLimit: writeLimit
+ },
+ schema: {
+ body: z.object({
+ tenantId: z.string(),
+ slug: slugSchema({ max: 64 })
+ }),
+ response: {
+ 200: sanitizedMicrosoftTeamsIntegrationSchema
+ }
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ const microsoftTeamsIntegration = await server.services.microsoftTeams.createMicrosoftTeamsIntegration({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId,
+ ...req.body
+ });
+
+ return microsoftTeamsIntegration;
+ }
+ });
+ server.route({
+ method: "GET",
+ url: "/",
+ config: {
+ rateLimit: readLimit
+ },
+ schema: {
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
+ response: {
+ 200: sanitizedMicrosoftTeamsIntegrationSchema.array()
+ }
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ const microsoftTeamsIntegrations = await server.services.microsoftTeams.getMicrosoftTeamsIntegrationsByOrg({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId
+ });
+
+ return microsoftTeamsIntegrations;
+ }
+ });
+
+ server.route({
+ method: "POST",
+ url: "/:id/installation-status",
+ config: {
+ rateLimit: readLimit
+ },
+ schema: {
+ params: z.object({
+ id: z.string()
+ })
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ await server.services.microsoftTeams.checkInstallationStatus({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId,
+ workflowIntegrationId: req.params.id
+ });
+ }
+ });
+
+ server.route({
+ method: "DELETE",
+ url: "/:id",
+ config: {
+ rateLimit: writeLimit
+ },
+ schema: {
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
+ params: z.object({
+ id: z.string()
+ }),
+ response: {
+ 200: sanitizedMicrosoftTeamsIntegrationSchema
+ }
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ const deletedMicrosoftTeamsIntegration = await server.services.microsoftTeams.deleteMicrosoftTeamsIntegration({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId,
+ id: req.params.id
+ });
+
+ return deletedMicrosoftTeamsIntegration;
+ }
+ });
+
+ server.route({
+ method: "GET",
+ url: "/:id",
+ config: {
+ rateLimit: readLimit
+ },
+ schema: {
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
+ params: z.object({
+ id: z.string()
+ }),
+ response: {
+ 200: sanitizedMicrosoftTeamsIntegrationSchema
+ }
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ const microsoftTeamsIntegration = await server.services.microsoftTeams.getMicrosoftTeamsIntegrationById({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId,
+ id: req.params.id
+ });
+
+ return microsoftTeamsIntegration;
+ }
+ });
+
+ server.route({
+ method: "PATCH",
+ url: "/:id",
+ config: {
+ rateLimit: writeLimit
+ },
+ schema: {
+ security: [
+ {
+ bearerAuth: []
+ }
+ ],
+ params: z.object({
+ id: z.string()
+ }),
+ body: z.object({
+ slug: slugSchema({ max: 64 }).optional(),
+ description: z.string().optional()
+ }),
+ response: {
+ 200: sanitizedMicrosoftTeamsIntegrationSchema
+ }
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ const microsoftTeamsIntegration = await server.services.microsoftTeams.updateMicrosoftTeamsIntegration({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId,
+ id: req.params.id,
+ ...req.body
+ });
+
+ return microsoftTeamsIntegration;
+ }
+ });
+
+ server.route({
+ method: "GET",
+ url: "/:workflowIntegrationId/teams",
+ config: {
+ rateLimit: readLimit
+ },
+ schema: {
+ params: z.object({
+ workflowIntegrationId: z.string()
+ }),
+ response: {
+ 200: z
+ .object({
+ teamId: z.string(),
+ teamName: z.string(),
+ channels: z
+ .object({
+ channelName: z.string(),
+ channelId: z.string()
+ })
+ .array()
+ })
+ .array()
+ }
+ },
+ onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
+ handler: async (req) => {
+ const teams = await server.services.microsoftTeams.getTeams({
+ actor: req.permission.type,
+ actorId: req.permission.id,
+ actorAuthMethod: req.permission.authMethod,
+ actorOrgId: req.permission.orgId,
+ workflowIntegrationId: req.params.workflowIntegrationId
+ });
+
+ return teams;
+ }
+ });
+
+ server.route({
+ method: "POST",
+ url: "/message-endpoint",
+ schema: {
+ body: z.any(),
+ response: {
+ 200: z.any()
+ }
+ },
Greptile
greptile
logic: Missing rate limiting and authentication on message-endpoint route. Add config.rateLimit and onRequest: verifyAuth to prevent DoS attacks
suggested fix
server.route({
method: "POST",
url: "/message-endpoint",
config: {
rateLimit: writeLimit
},
schema: {
body: z.any(),
response: {
200: z.any()
}
},
diff block
};
}
- @Throttle({ default: { limit: 10, ttl: 60 * 1000 } })
+ @Throttle({
+ default: {
+ limit: config.throttle.auth.limit,
+ ttl: config.throttle.auth.ttl,
+ },
+ })
Greptile
greptile
logic: Missing rate limit decorators on signup and signup-provider endpoints. These authentication endpoints should also be protected against brute force attacks.
suggested fix
@Throttle({
default: {
limit: config.throttle.auth.limit,
ttl: config.throttle.auth.ttl,
},
})
+ @Post('signup')