diff --git a/backend/src/server/config/rateLimiter.ts b/backend/src/server/config/rateLimiter.ts index 8c41eb2fa..0e40f286f 100644 --- a/backend/src/server/config/rateLimiter.ts +++ b/backend/src/server/config/rateLimiter.ts @@ -69,8 +69,15 @@ export const creationLimit: RateLimitOptions = { // Public endpoints to avoid brute force attacks export const publicEndpointLimit: RateLimitOptions = { - // Shared Secrets + // Read Shared Secrets timeWindow: 60 * 1000, max: 30, keyGenerator: (req) => req.realIp }; + +export const publicSecretShareCreationLimit: RateLimitOptions = { + // Create Shared Secrets + timeWindow: 60 * 1000, + max: 5, + keyGenerator: (req) => req.realIp +}; diff --git a/backend/src/server/routes/v1/secret-sharing-router.ts b/backend/src/server/routes/v1/secret-sharing-router.ts index ef53d121a..4ec2737fb 100644 --- a/backend/src/server/routes/v1/secret-sharing-router.ts +++ b/backend/src/server/routes/v1/secret-sharing-router.ts @@ -1,7 +1,12 @@ import { z } from "zod"; import { SecretSharingSchema } from "@app/db/schemas"; -import { publicEndpointLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter"; +import { + publicEndpointLimit, + publicSecretShareCreationLimit, + readLimit, + writeLimit +} from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; @@ -82,9 +87,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => iv: z.string(), tag: z.string(), hashedHex: z.string(), - expiresAt: z - .string() - .refine((date) => date === undefined || new Date(date) > new Date(), "Expires at should be a future date"), + expiresAt: z.string(), expiresAfterViews: z.number() }), response: { @@ -111,7 +114,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => method: "POST", url: "/", config: { - rateLimit: writeLimit + rateLimit: publicSecretShareCreationLimit }, schema: { body: z.object({ @@ -119,9 +122,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => iv: z.string(), tag: z.string(), hashedHex: z.string(), - expiresAt: z - .string() - .refine((date) => date === undefined || new Date(date) > new Date(), "Expires at should be a future date"), + expiresAt: z.string(), expiresAfterViews: z.number() }), response: { diff --git a/backend/src/services/secret-sharing/secret-sharing-service.ts b/backend/src/services/secret-sharing/secret-sharing-service.ts index ceb3d3896..48332f7b9 100644 --- a/backend/src/services/secret-sharing/secret-sharing-service.ts +++ b/backend/src/services/secret-sharing/secret-sharing-service.ts @@ -1,5 +1,5 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; -import { UnauthorizedError } from "@app/lib/errors"; +import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { TSecretSharingDALFactory } from "./secret-sharing-dal"; import { @@ -36,6 +36,10 @@ export const secretSharingServiceFactory = ({ } = createSharedSecretInput; const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); if (!permission) throw new UnauthorizedError({ name: "User not in org" }); + + if (new Date(expiresAt) < new Date()) { + throw new BadRequestError({ message: "Expiration date cannot be in the past" }); + } const newSharedSecret = await secretSharingDAL.create({ encryptedValue, iv, @@ -51,6 +55,10 @@ export const secretSharingServiceFactory = ({ const createPublicSharedSecret = async (createSharedSecretInput: TCreatePublicSharedSecretDTO) => { const { encryptedValue, iv, tag, hashedHex, expiresAt, expiresAfterViews } = createSharedSecretInput; + if (new Date(expiresAt) < new Date()) { + throw new BadRequestError({ message: "Expiration date cannot be in the past" }); + } + const newSharedSecret = await secretSharingDAL.create({ encryptedValue, iv, diff --git a/frontend/src/const.ts b/frontend/src/const.ts index 657145b39..880d2f021 100644 --- a/frontend/src/const.ts +++ b/frontend/src/const.ts @@ -25,7 +25,7 @@ export const publicPaths = [ "/login/sso", "/admin/signup", "/shared/secret/[id]", - "/shared/secret" + "/share-secret" ]; export const languageMap = { diff --git a/frontend/src/pages/shared/secret/index.tsx b/frontend/src/pages/share-secret/index.tsx similarity index 100% rename from frontend/src/pages/shared/secret/index.tsx rename to frontend/src/pages/share-secret/index.tsx