mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-21 19:59:39 -05:00
fix: add rate limiting and feature flag guard to isSurveyResponsePresentAction (ENG-942)
- Apply IP rate limit (10/min) to isSurveyResponsePresentAction to prevent email-enumeration oracle attacks against the single-response-per-email feature - Guard the action behind a server-side isSingleResponsePerEmailEnabled check so response presence cannot be probed on surveys where the feature is disabled - Apply IP rate limit (10/min) to validateSurveyPinAction to prevent brute-force PIN guessing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,16 @@ export const rateLimitConfigs = {
|
||||
allowedPerInterval: 10,
|
||||
namespace: "action:send-link-survey-email",
|
||||
}, // 10 per hour
|
||||
isSurveyResponsePresent: {
|
||||
interval: 60,
|
||||
allowedPerInterval: 10,
|
||||
namespace: "action:survey-response-present",
|
||||
}, // 10 per minute — prevents email-enumeration oracle
|
||||
validateSurveyPin: {
|
||||
interval: 60,
|
||||
allowedPerInterval: 10,
|
||||
namespace: "action:validate-survey-pin",
|
||||
}, // 10 per minute — prevents brute-force PIN guessing
|
||||
licenseRecheck: { interval: 60, allowedPerInterval: 5, namespace: "action:license-recheck" }, // 5 per minute
|
||||
},
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ const ZValidateSurveyPinAction = z.object({
|
||||
export const validateSurveyPinAction = actionClient
|
||||
.inputSchema(ZValidateSurveyPinAction)
|
||||
.action(async ({ parsedInput }) => {
|
||||
await applyIPRateLimit(rateLimitConfigs.actions.validateSurveyPin);
|
||||
|
||||
// Get survey data which includes pin information
|
||||
const survey = await getSurveyWithMetadata(parsedInput.surveyId);
|
||||
if (!survey) {
|
||||
@@ -62,5 +64,13 @@ const ZIsSurveyResponsePresentAction = z.object({
|
||||
export const isSurveyResponsePresentAction = actionClient
|
||||
.inputSchema(ZIsSurveyResponsePresentAction)
|
||||
.action(async ({ parsedInput }) => {
|
||||
await applyIPRateLimit(rateLimitConfigs.actions.isSurveyResponsePresent);
|
||||
|
||||
const survey = await getSurveyWithMetadata(parsedInput.surveyId);
|
||||
|
||||
if (!survey.isSingleResponsePerEmailEnabled) {
|
||||
throw new InvalidInputError("SINGLE_RESPONSE_PER_EMAIL_NOT_ENABLED");
|
||||
}
|
||||
|
||||
return await isSurveyResponsePresent(parsedInput.surveyId, parsedInput.email)();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user